XSLT Reference
xsl:for-each
Iterates over a node-set or sequence, applying the contained template body to each item in document order.
<xsl:for-each select="node-set">Description
xsl:for-each selects a set of nodes (or, in XSLT 2.0+, a sequence of items) and processes each one in turn. Within the loop body, the context node changes to the current item, so XPath expressions are evaluated relative to it.
It is the standard way to iterate over child elements or any repeated node structure when you do not want to use recursive template matching. The loop body can contain any sequence of XSLT instructions: output elements, xsl:value-of, nested xsl:for-each calls, conditionals, and so on.
An optional xsl:sort child element placed immediately inside xsl:for-each (before any other content) changes the processing order without altering the source document.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
select | XPath expression | Yes | Node-set or sequence to iterate over. |
Child element: xsl:sort
Place one or more xsl:sort elements as the first children to sort the selected set before processing.
| Attribute | Description |
|---|---|
select | XPath expression used as the sort key. |
order | "ascending" (default) or "descending". |
data-type | "text" (default) or "number". |
Examples
Iterate over child elements
Input XML:
<?xml version="1.0" encoding="UTF-8"?>
<catalog>
<item id="1"><name>Widget</name><price>9.99</price></item>
<item id="2"><name>Gadget</name><price>24.99</price></item>
<item id="3"><name>Doohickey</name><price>4.49</price></item>
</catalog>
Stylesheet:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/catalog">
<ul>
<xsl:for-each select="item">
<li>
<xsl:value-of select="name"/>
<xsl:text> — $</xsl:text>
<xsl:value-of select="price"/>
</li>
</xsl:for-each>
</ul>
</xsl:template>
</xsl:stylesheet>
Output:
<ul>
<li>Widget — $9.99</li>
<li>Gadget — $24.99</li>
<li>Doohickey — $4.49</li>
</ul>
Sorted iteration
Stylesheet (sort by price descending):
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/catalog">
<ul>
<xsl:for-each select="item">
<xsl:sort select="price" data-type="number" order="descending"/>
<li>
<xsl:value-of select="concat(name, ' — $', price)"/>
</li>
</xsl:for-each>
</ul>
</xsl:template>
</xsl:stylesheet>
Output:
<ul>
<li>Gadget — $24.99</li>
<li>Widget — $9.99</li>
<li>Doohickey — $4.49</li>
</ul>
Notes
position()andlast()inside the loop refer to the position within the selected set, not the original document position.current()inside the loop returns the same node as.(the context node). It becomes useful whencurrent()is called inside a predicate.- For grouping scenarios (e.g., group items by category) prefer
xsl:for-each-group(XSLT 2.0+) over the Muenchian method withxsl:for-each. - Template rules (
xsl:apply-templates) are generally more flexible and reusable thanxsl:for-each; usexsl:for-eachwhen the transformation logic is short and self-contained.