What Are current-group and current-grouping-key in XSLT?
In XSLT 2.0 and later versions, current-group() and
current-grouping-key() are built-in functions designed
specifically for working within the
<xsl:for-each-group> instruction. They provide direct
access to the items being processed inside a particular group and the
evaluation key that formed that group. Together, they eliminate the
complex, inefficient Muenchian grouping techniques required in XSLT 1.0,
enabling clear, declarative transformations for structured and flat XML
datasets.
The Role of
<xsl:for-each-group>
Before examining the functions, it is essential to understand the
parent element: <xsl:for-each-group>. This
instruction iterates over a sequence of items and partitions them into
distinct subsets based on an algorithm defined by one of several
attributes:
group-by: Groups items sharing the exact same computed key.group-adjacent: Groups consecutive sibling items that share the same computed key.group-starting-with: Starts a new group whenever an item matches a specific pattern.group-ending-with: Ends the current group whenever an item matches a specific pattern.
During each iteration of <xsl:for-each-group>,
XSLT makes the current group's data accessible via
current-group() and
current-grouping-key().
Understanding
current-group()
The current-group() function returns a sequence
containing all the items (nodes or atomic values) that belong to the
group currently being processed in the loop iteration.
Key Characteristics
- Return Type: A sequence of nodes or atomic values.
- Context Dependency: It can only be evaluated inside
the body of an
<xsl:for-each-group>instruction or within a template/function called from inside it where the dynamic context is preserved. - Usage: It allows you to loop over the grouped
members, apply templates to them, or compute aggregate values such as
count(current-group())orsum(current-group()/price).
Example
Given a flat list of employee records:
<employees>
<emp department="IT" name="Alice"/>
<emp department="HR" name="Bob"/>
<emp department="IT" name="Charlie"/>
</employees>You can group by department and process each member:
<xsl:for-each-group select="employees/emp" group-by="@department">
<department name="{@department}">
<xsl:for-each select="current-group()">
<member><xsl:value-of select="@name"/></member>
</xsl:for-each>
</department>
</xsl:for-each-group>Understanding
current-grouping-key()
The current-grouping-key() function returns the atomic
value that represents the key shared by all members of the current
group.
Key Characteristics
- Return Type: An atomic value (such as a string,
integer, or date) representing the evaluation of the
group-byorgroup-adjacentexpression. - Availability: It is strictly populated when using
group-byorgroup-adjacent. If the grouping algorithm usesgroup-starting-withorgroup-ending-with,current-grouping-key()returns an empty sequence (empty()) because those modes operate on node patterns rather than computed key values. - Usage: It prevents the need to query the first node
of the group (e.g.,
current-group()[1]/@department) just to retrieve the category label.
Example
Using current-grouping-key() to dynamically construct
wrapper elements:
<xsl:for-each-group select="employees/emp" group-by="@department">
<department name="{current-grouping-key()}" total-staff="{count(current-group())}">
<xsl:apply-templates select="current-group()"/>
</department>
</xsl:for-each-group>Summary of Functional Differences
current-group()retrieves the content of the partition (the nodes or items themselves).current-grouping-key()retrieves the identifier of the partition (the calculated grouping value).
By utilizing these two functions inside
<xsl:for-each-group>, stylesheets remain concise,
maintainable, and significantly more performant than legacy XSLT 1.0
key-based workarounds.