xsl:for-each-group
Partitions a sequence into groups and executes its body once per group.
<xsl:for-each-group select="employee" group-by="@department">
...
</xsl:for-each-group>Exactly one of group-by, group-adjacent, group-starting-with, or group-ending-with must be present. Inside the body, current-group() returns the items in the current group, and current-grouping-key() returns the key for group-by and group-adjacent groupings. The body runs in the context of the first item of each group.
group-by collects all items with the same key into one group regardless of order. group-adjacent only joins consecutive items with the same key into one group. group-starting-with and group-ending-with use a match pattern to delimit groups.
Attributes
| Attribute | Description |
|---|---|
select |
XPath expression producing the population to group. Required. |
group-by |
XPath expression producing the grouping key. |
group-adjacent |
XPath expression producing the grouping key; only adjacent items are joined. |
group-starting-with |
Pattern that begins a new group. |
group-ending-with |
Pattern that ends the current group. |
Examples
Grouping by department:
<xsl:for-each-group select="employee" group-by="@department">
<dept name="{current-grouping-key()}">
<xsl:for-each select="current-group()">
<emp><xsl:value-of select="@name"/></emp>
</xsl:for-each>
</dept>
</xsl:for-each-group>Adjacent grouping — collapse runs of <text> nodes into paragraphs, keeping <break> nodes alone:
<xsl:for-each-group select="*" group-adjacent="name()">
<xsl:choose>
<xsl:when test="current-grouping-key() = 'text'">
<p><xsl:value-of select="current-group()" separator=" "/></p>
</xsl:when>
<xsl:otherwise>
<xsl:copy-of select="current-group()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>group-starting-with — split a flat list of headings and paragraphs into sections:
<xsl:for-each-group select="*" group-starting-with="h1">
<section>
<xsl:copy-of select="current-group()"/>
</section>
</xsl:for-each-group>