Archive
Unique key grouping with multiple input documents and nodesets in variables
The problem
A common requirement in XSL transformations is to group unsorted data by a key unique to each group, and sort it for display. For example:
<?xml version="1.0"?> <food> <item type="Fruit" name="Orange" /> <item type="Vegetable" name="Cucumber" /> <item type="Meat" name="Chicken" /> <item type="Vegetable" name="Carrot" /> <item type="Vegetable" name="Potato" /> <item type="Meat" name="Pork" /> <item type="Fruit" name="Banana" /> <item type="Fruit" name="Apple" /> </food>
We may typically want to output an HTML table with each food type (Fruit, Meat, Vegetable) as a header with all the items in each food category as table rows/records, ie.
Fruit |
Apple |
Banana |
Orange |
Meat |
Chicken |
Pork |
Vegetable |
Carrot |
Cucumber |
Potato |
When dealing with a single input document addressed directly (ie. not through a variable), this is a trivial problem for XSL, easily solvable using <xsl:key>
and key()
.
This technique fails when you must group a node-set stored in a variable or in an external document referenced with document()
because <xsl:key>
does not allow you to use variables or document()
in its attributes – it is only capable of indexing the main source document. Additionally, XPath axes we might use for testing uniqueness in a set (typically preceding-sibling::
in an <xsl:for-each>
to see if we have found the first occurrence of a new group key) do not function on external documents referenced by document()
.
So how do we group with XSL variables or multiple input documents? Read more…