Smart Grouping Using XSLT

06Oct06 Steven

XSL is a relatively small language, yet it can do some pretty neat things. I’m glad for that, as I thought I had hit a road block and was going to have to abandon all hope.

If you have some XML that needs to be grouped uniquely by something, you can use an XPath expression and the apply-templates element. Let’s say you have a multiuser blog and want to format some output showing the user name and all of their posts. Assume each node is laid out similar to this:


<post>
<user>John</user>
<title>My blog post</title
</post>
<post>
<user>John</user>
<title>Another blog post</title
</post>
<post>
<user>Julie</user>
<title>Hello there</title
</post>

Normally, issuing a for-each and value-of statements over the post element would work, but it’d print John twice. It’d be nicer to print each person’s name once, then list all their posts beneath their name.

You can do this using the Muenchian method.

First you need to create a key that indexes all post’s. Immediately beneath the xsl:stylesheet definition, do this:

<xsl:key name="authors" match="post" use="name" />

This names the key authors, and looks at all post nodes, using the name element to index.

Now add the following to wherever you want this list to appear in your document.

<xsl:apply-templates select="post[generate-id(.) = generate-id(key('authors',name)[1])]" />

That’s confusing to me, but it’s pretty much straight out of the document linked to above. Somehow we’re selecting each author and grouping all their posts together.

Finally, write a template that uses this data and outputs it. I was outputting html, so I had to move the xsl:template definition outside my current template section (I have one main xsl:template declaration that wraps the html body and end body elements) Not to worry, the xsl:apply-templates will invoke the output of the one we’re about to create, so we can place the list into the body of the html.

<xsl:template match="post" >
<xsl:value-of select="name" />
<xsl:for-each select="key('authors',name)" >
<xsl:value-of: select="title" />
</xsl:for-each>

For someone expert on this, check out Jeni Tennison.


No Responses to “Smart Grouping Using XSLT”  

  1. No Comments

Leave a Reply



 

Bad Behavior has blocked 71 access attempts in the last 7 days.