One frequent requirement is [bi]grouping[/bi]. Grouping is the act of sorting things into a certain order and then coalescing the data for all things that have the same value for the sort key. For example, if you have data for a library of books, you might use grouping to create a report of books sorted by author, with a pretty visual break between authors and a count of books by each author.
In XML, we sort XML elements and use as the sort key the value of an attribute or subordinate element.
XSLT version 2 will have grouping as a [link http://www.w3.org/TR/xslt20/#grouping]native feature[/link], but most of us are using version 1 XSLT processors. So how do we do grouping?
There are many techniques to achieve grouping, many of which are rather brute-force approaches. However, the Muench method is perhaps the most flexible grouping method to be devised for XSLT version 1. The Muench method is named after Steve Muench, who developed this method as the Oracle XML Evangelist.
For example, let's use this XML document taken from a recent thread. The Tek-Tips poster wanted to group entries based on the value of xpos so that he could report all of the ypos values for each xpos.
[code XML data document]
<?xml version="1.0"?>
<availableSeats>
<Table>
<xpos>8</xpos>
<ypos>2</ypos>
<seat_Status>4</seat_Status>
</Table>
<Table>
<xpos>7</xpos>
<ypos>2</ypos>
<seat_Status>4</seat_Status>
</Table>
<Table>
<xpos>7</xpos>
<ypos>1</ypos>
<seat_Status>4</seat_Status>
</Table>
<Table>
<xpos>9</xpos>
<ypos>3</ypos>
<seat_Status>4</seat_Status>
</Table>
</availableSeats>[/code]
[color blue]<!-- Add an index (key) that allows selection based on the value of xpos -->[/color]
<xsl:key name="X" match="Table" use="xpos"/>
<xsl:template match="/">
<table border="1"> [color blue]<!-- The outer for-each selects the first Table node for every unique xpos value.
In other words, the outer for-each will iterate exactly once for each unique
value of xpos. -->[/color]
<xsl:for-each select="//Table[generate-id(.)=generate-id(key('X', xpos)[1])]">
<xsl:sort select="xpos"/>
<tr><td><strong><xsl:text>XPOS=</xsl:text><xsl:value-of select="xpos"/></strong></td></tr> [color blue]<!-- The inner for-each iterates over all nodes that match the outer for-each xpos value -->[/color]
<xsl:for-each select="key('X', xpos)">
<xsl:sort select="ypos"/>
<tr><td><xsl:text>YPOS=</xsl:text><xsl:value-of select="ypos"/></td></tr>
</xsl:for-each>
</xsl:for-each>
</table>
</xsl:template>
</xsl:stylesheet>[/code]
Obviously it is crucial that there be careful matching between the attributes in the xsl:key element and the xsl:for-each and xsl:sort elements.
This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
By continuing to use this site, you are consenting to our use of cookies.