Simple XSLT & XPath grouping
page 1 of 1
Published: 26 Sep 2003
Unedited - Community Contributed
Abstract
Examples and discussion how to utilize grouping or selecting distinct nodes from XML document using XSLT or plain XPath.
by Teemu Keiski
Feedback
Average Rating: This article has not yet been rated.
Views (Total / Last 10 Days): 43375/ 44

The article

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



User Comments

Title: Right on Money   
Name: Ab
Date: 2011-03-23 9:45:21 PM
Comment:
I have been trying to find this for a while.. This is right on money!! Execellent..
Title: Very useful   
Name: Ulf
Date: 2009-08-14 7:30:03 AM
Comment:
Thanks a lot that's very useful
Title: Great   
Name: Zeeshan
Date: 2009-05-27 5:02:14 AM
Comment:
Great work
Title: You little beauty   
Name: Sean
Date: 2009-04-02 7:09:41 PM
Comment:
Thank you! It works like a charm.
Title: Genius work   
Name: Sam
Date: 2009-03-06 9:16:00 AM
Comment:
Wow. I saw so many different ways of doing this, most (if not all) of them using xsl:key.

This is the simplest way so far. Great job.
Title: Amazing   
Name: Pranjali Bhide
Date: 2008-02-13 2:12:14 AM
Comment:
Very useful.
Thanks a lot!
Title: very useful   
Name: Mark
Date: 2007-10-25 4:59:42 AM
Comment:
This was very helpful to me. Thank you.
Title: Well...   
Name: Teemu
Date: 2005-04-19 3:44:41 PM
Comment:
As you probably get from the context the node is whatever you want to query from the document. It is a generalized concept, take XML document for example where a "node" can refer to an attribute or it can refer to an element.

So what you mean with "node" is what you think with a node. In this case it is distinct values from manufacturers of cars, because car is the "node", what we are interested in this XML document, the distinct values of cars based on manufacturers. And by no means this is not limited to the siblings as there are other approaches to the grouping (check my other article which demonstrates the use of keys)

If you have something that you don't understand, or something else regarding the implementation, by all means use the feedback form to contact me, or email me directly at joteke (@) aspalliance.com.

Thanks
Title: Re   
Name: Doug
Date: 2005-04-19 1:46:53 PM
Comment:
I would expect it to "Select distinct nodes" as the title sugests...
Title: Very obvious thing...   
Name: Teemu
Date: 2005-04-19 12:21:06 PM
Comment:
You are stating the obvious...what would you expect it to do, as that's the intended logic. ;-)
Title: Bug   
Name: Doug
Date: 2005-04-19 11:38:38 AM
Comment:
This does not work if the two nodes are not next to each other and you must sort on somethign else besides manfacturer....

Product Spotlight
Product Spotlight 





Community Advice: ASP | SQL | XML | Regular Expressions | Windows


©Copyright 1998-2017 ASPAlliance.com  |  Page Processed at 2017-07-26 8:42:47 PM  AspAlliance Recent Articles RSS Feed
About ASPAlliance | Newsgroups | Advertise | Authors | Email Lists | Feedback | Link To Us | Privacy | Search