I was thinking of writing a quick program that would process my iTunes XML-exported playlists into HTML. After some thought on what would be the simplest way, I decided it might be time to overcome my distaste for XSLT, and give it another go.
So I pulled out my trusty O'Reilly XSLT book and tried to gauge just how much effort was going to be required. I came across the following description of the "recommended" way of grouping nodes after a sort so you don't have to repeat information (like album title) for each entry. This was a basic requirement: if I didn't want to group, I could just apply a CSS stylesheet directly to the XML document and be done with it.
In a procedural language, this would be most easily done by, after sorting the tracks, keeping track of the value of the album title from the last pass through the loop, and checking if it's changed. In XSLT, it's not quite so simple.
In the book's example, we are trying to group addresses by their ZIP code. Note, this is the second attempt to explain how it's done.
For each
<address>
, we use thekey()
function to retrieve all<address>
es that have the same<zip>
. We then take the first node from that node-set. Finally we use thegenerate-id()
function to generate anid
for both nodes. If the two generatedid
s are identical, then the two nodes are the same.
Whew. Let me catch my breath.
If this
<address>
matches the first node returned by thekey()
function, then we know we've found the first<address>
that matches this grouping value. Selecting all of the first values (remember, our previous predicate ends with[1]
) gives us a node-set of some number of<address>
elements, each of which contains one of the unique grouping values we need.
The explanation continues for another page, and revolves around the XPath expression: //address[generate-id(.)=generate-id(key('zipcodes', zip)[1])]
At this point, I started thinking I'd been right about XSLT in the first place.