Group XML elements by key using XSLT v2.0
Tested with Saxon on
|Debian (Lenny, Squeeze)|
|Ubuntu (Intrepid, Jaunty, Karmic, Lucid, Maverick, Natty, Precise, Trusty)|
To organise a set of XML elements into groups, such that elements with the same key are placed in the same group, and elements with different keys are placed in different groups
XSLT v2.0 introduced direct support for grouping my means of the
for-each-group element. This is more readable than the Muenchian method, and potentially more efficient too. The only significant drawback is that an XSLT v2.0-compatible processor is needed. (At the time of writing Saxon supported XSLT v2.0 but xsltproc and Xalan did not.)
for-each-group element, the functions
current-group can be used to gain access to the current value of the key and the set of nodes that correspond to that key.
Here is a complete stylesheet to perform the task specified in the scenario (grouping Subversion log entries by path):
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"> <xsl:template match="/log"> <log> <xsl:for-each-group select="//path" group-by="text()"> <pathentry> <path><xsl:value-of select="current-grouping-key()"/></path> <xsl:for-each select="current-group()"> <logentry> <xsl:attribute name="revision"><xsl:value-of select="ancestor::logentry/@revision"/></xsl:attribute> <xsl:attribute name="action"><xsl:value-of select="@action"/></xsl:attribute> <xsl:attribute name="date"><xsl:value-of select="ancestor::logentry/date/text()"/></xsl:attribute> </logentry> </xsl:for-each> </pathentry> </xsl:for-each-group> </log> </xsl:template> </xsl:stylesheet>
For sample input and output documents see Group XML elements by key using XSLT.
To apply the stylesheet using Saxon see Process an XML document using an XSLT stylesheet.
At the time of writing this stylesheet is not expected to work with xsltproc or Xalan due to lack of XSLT v2.0 compatibility.