An XSLT Anecdote

November 2, 2003 6:12 PM

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 the key() function to retrieve all <address>es that have the same <zip>. We then take the first node from that node-set. Finally we use the generate-id() function to generate an id for both nodes. If the two generated ids are identical, then the two nodes are the same.

Whew. Let me catch my breath.

If this <address> matches the first node returned by the key() 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.


"In a procedural language, this would be most easily done by..." - That is your first big mistake. For some strange reason XSLT has always just made sense to me, the same way OO has always just made sense. I see people all around me (I work in a University, currently as a tutor and PhD student) struggling with it and I sometimes find it hard to understand why. The biggest problem is that it is the completely different mindset that is required to work in the declarative rather then the procedural. I've found that the best way to tackle new problems is to just put aside all that I know about something I may think is "similar" and attempt to approach it fresh, lest I doom myself to unfairly projecting my biases onto what is in actuality a perfectly fine and logical technology. Naturally this is something far easier said then done :(

You are having the automatic rejection of a procedural programmer to a functional language. When I tried doing some pretty advanced stuff with XSLT, I suddenly realised "Hey! This is how I did it in LISP".

However, even after crossing this barrier, XML is a lousy markup for programming. XSLT is cool for simple operations, presentational stuff that can't really be done with CSS, but awfull for data processing.

I've also found it good for code generation. Not many people think to use it for non XML->XML transformations.

The functional mindset is the hardest part of XSLT, and grouping nodes together is the most common request that runs headlong into the functional brickwall. That's why XSLT 2 provides for it natively:

given your noted joy in ruby hacking, you might like Martin Fowler's use of ruby to replace XSLT:

Ruby was my first thought before XSLT, but the problem is that Ruby doesn't come packaged with an XML parser until v1.8, and even with the release of Panther, OS X ships with 1.6.8. So I'd have had to make installing REXML a prerequisite for using the application. Which would rather suck.

ahh... you didn't mention that your quick little program for exporting your playlists was actually planned to The Next Big Thing and make you a millionaire ;-)

Previously: Knights of the Old Republic

Next: Short Presentation on Blogging