Sample data
Sample XML data that both examples utilize is as follows.
<?xml version="1.0" encoding="utf-8" ?>
<cars>
<car manufacturer="Mazda" owner="Jason" />
<car manufacturer="Opel" owner="Teemu" />
<car manufacturer="Toyota" owner="Thomas" />
<car manufacturer="Opel" owner="Henry" />
<car manufacturer="Daimler" owner="Mika" />
<car manufacturer="Toyota" owner="Colt" />
<car manufacturer="Toyota" owner="Teemu" />
<car manufacturer="Daimler" owner="Jason" />
</cars>
[Download sample data]
Selecting distinct nodes
How to select distinct manufacturers from the sample data? Well, like this for example:
//car[not(@manufacturer=preceding-sibling::car/@manufacturer)]/@manufacturer
How it works? It drops any car element that have same manufacturer attribute value that preceding sibling car element has (if such value exists in other words).
[Download XSLT stylesheet]
Grouping by manufacturers in XSLT stylesheet
In this scenario selecting distinct manufacturer nodes is the key thing, although logic is bit more complicated. Distinct nodes are first selected into variable
<xsl:variable name="uniquemanufacturers" select="//car[not(@manufacturer=preceding-sibling::car/@manufacturer)]/@manufacturer" />
Then manufacturers are looped through using <xsl:for-each> and also in sorted order. For each manufacturer, car owners are queries as follows in the loop.
<xsl:variable name="owners" select="//car[@manufacturer=current()]/@owner" />
current() function refers to the current (context) node when for-each loop processing goes node by node. After this count of owners is printed out using
<xsl:value-of select="count($owners)" />
And finally car owners are listed in sorted order simply
<xsl:for-each select="$owners">
<xsl:sort select="." />
<xsl:value-of select="current()" /><br/>
</xsl:for-each>
[Download XSLT stylesheet]
Conclusion
I have demonstrated with simple examples how selecting distinct nodes and grouping can happen. You should be able to utilize this in your own stylesheets easily.
Related resources
Creating a Web.config Editor - Part 1 by Jason Gaylord
Creating a Web.config Editor - Part 2 by Jason Gaylord