Grouping

Grouping by some element, attribute or a computed value is a common thing to do and the Muenchian grouping is an efficient way to do it with XSLT. Jeni Tennison's Grouping Using the Muenchian Method is very helpful here.

An example

Here's some XML for William Shakespare's The Tragedy of Hamlet, Prince of Denmark, Act 3, Scene 1. That's where Hamlet gets to do his "To be, or not to be..." bit.

Click here to see the XML document for this play open in a new window.

Here's an XSLT stylesheet to group speeches by character

Now for the rocket surgery part...

There's a key, called character, for speech nodes, which uses the character element value to group speeches by character.
<xsl:key name="character" match="play/act/scene/speech" use="character"/>

Comparing an id generated for a node with the id generated for the first node in a group can test which is the first node in this group. So, here's how to find the first speech for each character.
<xsl:apply-templates select="play/act/scene/speech[generate-id(.)=generate-id(key('character',character)[1])]" mode="character">

Then to show all the speeches for this character
<xsl:apply-templates select="key('character',character)" mode="speech"/>

This is how the speeches for each character appear after transforming the XML with this stylesheet.

Click here to see this HTML open in a new window.

Another example

Things get a bit more complicated in this next example.

Here's an XSLT stylesheet to group speeches by character, then by act and then by scene

To group a character's speeches by act uses a key called act.
<xsl:key name="act" match="play/act/scene/speech" use="concat(character, '|', ../../title)"/>
To group a character's speeches in an act by scene uses a key called scene.
<xsl:key name="scene" match="play/act/scene/speech" use="concat(character, '|', ../../title, ../title)"/>
A key for a sub-group level needs parts from the keys for each group level above it to make it unique. Here, act is the key for a sub-group of a character's speeches in each act so a unique act key needs character and act parts. And scene is the key for a sub-group of a character's speeches in each scene of an act so a unique scene key needs character and act and scene parts. If that makes sense.

This is how the speeches for each character appear after transforming the XML for Hamlet with this stylesheet.

Click here to see this HTML open in a new window.