A Brute-Force Approach

One thing we could do is make the transformation in two passes; we could write an intermediate stylesheet to sort the names and generate a new XML document, and then use the stylesheet we’ve already written, because document order and sorted order will be the same. Here’s how that intermediate stylesheet would look:

<?xml version="1.0"?>
<!-- namegrouper2a.xsl -->
<xsl:stylesheet version="1.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:output method="xml" indent="no"/>

  <xsl:strip-space elements="*"/>

  <xsl:template match="/">
    <addressbook>
      <xsl:for-each select="addressbook/address">
        <xsl:sort select="name/zip"/>
        <xsl:copy-of select="."/>
      </xsl:for-each>
    </addressbook>
  </xsl:template>
</xsl:stylesheet>

This stylesheet generates a new <addressbook> document that has all of the <address> elements sorted correctly. We can then run our original stylesheet against the sorted document and get results that are closer to what we want:

Addresses grouped by zip code
Ms. Natalie Attired
707 Breitling Way


Zip code 02718 (Skunk Haven, MA):
Harry Backstayge
283 First Avenue

Mary Backstayge
283 First Avenue


Zip code 02930 (Lynn, MA):
Ms. Amanda Reckonwith
930-A Chestnut Street


Zip code 27318 (Boylston, VA):
Mary McGoon
103 Bryant Street


Zip code 48392 (Sheboygan, WI):
Mr. Chester Hasbrouck Frisby
1234 Main Street

There’s one more problem here: we don’t have a heading for the first group. Natalie Attired lives in Winter Harbor, Maine, but there’s no heading for Winter ...

Get XSLT, 2nd Edition now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.