mirror of
https://github.com/alexandrev/xslt-lab.git
synced 2026-09-20 04:23:16 +00:00
feat(blog): XSLT/XPath function reference section (Phase 2)
- 19 reference pages under /xslt/functions/ covering: xsl:value-of, xsl:for-each, xsl:for-each-group, xsl:function, xsl:iterate, last(), position(), count(), concat(), contains(), substring(), sum(), key(), current(), string-join(), tokenize(), matches(), replace(), format-date() - Each page: description, parameters table, return value, 2 runnable examples (input XML + stylesheet + output), notes, cross-links - New Hugo section with reference-specific layout (version badges, syntax block, "Try in Playground" CTA, parameters table styles) - Menu entry "Reference" → /xslt/functions/ - CSS: .ref-badge, .ref-syntax, .ref-index-list, .ref-try + table styles Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,120 @@
|
||||
---
|
||||
title: "xsl:for-each"
|
||||
description: "Iterates over a node-set or sequence, applying the contained template body to each item in document order."
|
||||
date: 2026-04-18T00:00:00Z
|
||||
version: "1.0"
|
||||
versionLabel: "XSLT 1.0"
|
||||
category: "element"
|
||||
syntax: "<xsl:for-each select=\"node-set\">"
|
||||
tags: ["xslt", "reference", "xslt1"]
|
||||
---
|
||||
|
||||
## 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
|
||||
<?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
|
||||
<?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:**
|
||||
```xml
|
||||
<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
|
||||
<?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:**
|
||||
```xml
|
||||
<ul>
|
||||
<li>Gadget — $24.99</li>
|
||||
<li>Widget — $9.99</li>
|
||||
<li>Doohickey — $4.49</li>
|
||||
</ul>
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- `position()` and `last()` 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 when `current()` 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 with `xsl:for-each`.
|
||||
- Template rules (`xsl:apply-templates`) are generally more flexible and reusable than `xsl:for-each`; use `xsl:for-each` when the transformation logic is short and self-contained.
|
||||
|
||||
## See also
|
||||
|
||||
- [xsl:for-each-group](../xsl-for-each-group)
|
||||
- [position()](../xpath-position)
|
||||
- [last()](../xpath-last)
|
||||
Reference in New Issue
Block a user