XPath Node Set
A node set is a set of nodes. When you write an XPath expression to return one or more nodes, you call these nodes a node set.
For example, if you use the following expression to return a node called "title", you will have a set of nodes all called "title" (assuming there's more than one record).
child::title
Node Set Functions
You can use the following functions when working with node sets:
| Function | Description |
|---|---|
| last() | Returns the number of nodes in a node set. |
| position() | Returns the position of the context node (current node). The starting value is 1. As you loop through each node, the position increments. |
| count(node1, node2, ...) | Returns the total number of nodes in the node set as provided between the parentheses. If you leave the parentheses blank, it will use the context node. |
| id((string1, string2, ...) node) | Returns the nodes whose ID matches the string/s passed to the function. |
| local-name(node_set) | Returns the local name of the first node in the node set. The local name is the name without the namespace prefix. To use the context node, simply leave node_set blank. |
| namespace-uri(node_set) | Returns the URI of the namespace of the first node in the node set. To use the context node, leave node_set blank. |
| name(node_set) | Returns the full, qualified name of the first node in the node set. To use the context node, simply leave node_set blank. |
Node Set Function Example
The Source XML File
Imagine we have the following XML file:
<?xml version="1.0"?>
<food_list>
<food_item type="vegetable">
<name>Agar</name>
<carbs_per_serving>81</carbs_per_serving>
<fiber_per_serving>8</fiber_per_serving>
<fat_per_serving>0.5</fat_per_serving>
<kj_per_serving>1280</kj_per_serving>
</food_item>
<food_item type="vegetable">
<name>Asparagus</name>
<carbs_per_serving>1</carbs_per_serving>
<fiber_per_serving>1</fiber_per_serving>
<fat_per_serving>0</fat_per_serving>
<kj_per_serving>40</kj_per_serving>
</food_item>
<food_item type="vegetable">
<name>Cabbage</name>
<carbs_per_serving>0</carbs_per_serving>
<fiber_per_serving>1</fiber_per_serving>
<fat_per_serving>0</fat_per_serving>
<kj_per_serving>14</kj_per_serving>
</food_item>
<food_item type="vegetable">
<name>Potato</name>
<carbs_per_serving>21.5</carbs_per_serving>
<fiber_per_serving>2</fiber_per_serving>
<fat_per_serving>1</fat_per_serving>
<kj_per_serving>460</kj_per_serving>
</food_item>
<food_item type="vegetable">
<name>Pumpkin</name>
<carbs_per_serving>6</carbs_per_serving>
<fiber_per_serving>1</fiber_per_serving>
<fat_per_serving>0.5</fat_per_serving>
<kj_per_serving>150</kj_per_serving>
</food_item>
<food_item type="vegetable">
<name>Yam</name>
<carbs_per_serving>30.5</carbs_per_serving>
<fiber_per_serving>2</fiber_per_serving>
<fat_per_serving>0.5</fat_per_serving>
<kj_per_serving>550</kj_per_serving>
</food_item>
<food_item type="vegetable">
<name>Zucchini</name>
<carbs_per_serving>1.5</carbs_per_serving>
<fiber_per_serving>1.5</fiber_per_serving>
<fat_per_serving>0.5</fat_per_serving>
<kj_per_serving>55</kj_per_serving>
</food_item>
<food_item type="seafood">
<name>Abalone</name>
<carbs_per_serving>0</carbs_per_serving>
<fiber_per_serving>0</fiber_per_serving>
<fat_per_serving>1</fat_per_serving>
<kj_per_serving>400</kj_per_serving>
</food_item>
<food_item type="seafood">
<name>Barramundi</name>
<carbs_per_serving>0</carbs_per_serving>
<fiber_per_serving>0</fiber_per_serving>
<fat_per_serving>2</fat_per_serving>
<kj_per_serving>390</kj_per_serving>
</food_item>
<food_item type="fruit">
<name>Apple</name>
<carbs_per_serving>15</carbs_per_serving>
<fiber_per_serving>2.5</fiber_per_serving>
<fat_per_serving>0</fat_per_serving>
<kj_per_serving>250</kj_per_serving>
</food_item>
<food_item type="fruit">
<name>Kiwi Fruit</name>
<carbs_per_serving>7.5</carbs_per_serving>
<fiber_per_serving>2.5</fiber_per_serving>
<fat_per_serving>0</fat_per_serving>
<kj_per_serving>150</kj_per_serving>
</food_item>
<food_item type="grain">
<name>Oatbran</name>
<carbs_per_serving>62</carbs_per_serving>
<fiber_per_serving>14</fiber_per_serving>
<fat_per_serving>7</fat_per_serving>
<kj_per_serving>1400</kj_per_serving>
</food_item>
<food_item type="grain">
<name>Wheatgerm</name>
<carbs_per_serving>1.5</carbs_per_serving>
<fiber_per_serving>1</fiber_per_serving>
<fat_per_serving>0.5</fat_per_serving>
<kj_per_serving>70</kj_per_serving>
</food_item>
</food_list>
The Requirement
Now, imagine we want to display the contents of the file in a table, and that we want to have a "counter" column that provides the count of each row. Something like this:
The Solution
We could achieve the above requirement using the XPath position() function, as follows:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="food_list">
<table border="1" style="background-color:#cccc00">
<tr>
<th>Node Position</th>
<th>Food Item</th>
<th>Carbs (g)</th>
<th>Fiber (g)</th>
<th>Fat (g)</th>
<th>Energy (kj)</th>
</tr>
<xsl:for-each select="food_item">
<tr>
<td><b><xsl:value-of select="position()"/></b></td>
<td><xsl:value-of select="name"/></td>
<td><xsl:value-of select="carbs_per_serving"/></td>
<td><xsl:value-of select="fiber_per_serving"/></td>
<td><xsl:value-of select="fat_per_serving"/></td>
<td><xsl:value-of select="kj_per_serving"/></td>
</tr>
</xsl:for-each>
</table>
</xsl:template>
</xsl:stylesheet>

