Our First Example Sorting Data with xsl:sort
page 106 address
name first-nameHarryfirst-name
last-nameBackstaygelast-name name
street283 First Avenuestreet citySkunk Havencity
stateMAstate zip02718zip
address address
name first-nameMaryfirst-name
last-nameMcGoonlast-name name
street103 Bryant Streetstreet cityBoylstoncity
stateVAstate zip27318zip
address address
name titleMs.title
first-nameAmandafirst-name last-nameReckonwithlast-name
name street930-A Chestnut Streetstreet
cityLynncity stateMAstate
zip02930zip address
addressbook
Wed like to generate a list of these addresses, sorted by
last-name
. Well use the magical
xsl:sort
element to do the work. Our stylesheet looks like this:
?xml version=1.0? xsl:stylesheet version=1.0 xmlns:xsl=http:www.w3.org1999XSLTransform
xsl:output method=text indent=no xsl:strip-space elements=
xsl:variable name=newline xsl:text
xsl:text xsl:variable
xsl:template match= xsl:for-each select=addressbookaddress
xsl:sort select=namelast-name xsl:value-of select=nametitle
xsl:text xsl:text xsl:value-of select=namefirst-name
xsl:text xsl:text xsl:value-of select=namelast-name
xsl:value-of select=newline xsl:value-of select=street
xsl:value-of select=newline xsl:value-of select=city
xsl:text, xsl:text xsl:value-of select=state
xsl:text xsl:text xsl:value-of select=zip
xsl:value-of select=newline xsl:value-of select=newline
xsl:for-each xsl:template
xsl:stylesheet
page 107
The heart of our stylesheet are the
xsl:for-each
and
xsl:sort
elements. The
xsl:for- each
element selects the items with which well work, and the
xsl:sort
element rearranges them before we write them out.
Notice that were generating a text file
xsl:output method=text
. You could generate an HTML file or something more complicated if you want. To invoke the stylesheet engine,
we run this command:
java org.apache.xalan.xslt.Process -in names.xml -xsl namesorter1.xsl -out names.text
Here are the results we get from our first attempt at sorting:
Ms. Natalie Attired 707 Breitling Way
Winter Harbor, ME 00218 Mary Backstayge
283 First Avenue Skunk Haven, MA 02718
Harry Backstayge 283 First Avenue
Skunk Haven, MA 02718 Mr. Chester Hasbrouck Frisby
1234 Main Street Sheboygan, WI 48392
Mary McGoon 103 Bryant Street
Boylston, VA 27318 Ms. Amanda Reckonwith
930-A Chestnut Street Lynn, MA 02930
As you can see from the output, the addresses in our original document were sorted by last name. All we had to do was add
xsl:sort
to our stylesheet, and all the elements were magically reordered. If you arent convinced that XSLT can increase your programmer
productivity, try writing the Java code and DOM method calls to do the same thing. We can do a couple of things to improve our original stylesheet, however. For one thing,
theres an annoying blank space at the start of every name that doesnt have a
title
element. A more significant improvement is that wed like to sort addresses by
first-name
within
last-name
. In our last example, Mary Backstayge should appear after Harry Backstayge. Heres how we can modify our stylesheet to use more than one sort key:
xsl:template match= xsl:for-each select=addressbookaddress
xsl:sort select=namelast-name xsl:sort select=namefirst-name
...
Weve simply added a second
xsl:sort
element to our stylesheet. This element does what we want; it sorts the
address
elements by
first-name
within
last-name
. To be thoroughly obsessive about our output, we can use an
xsl:if
element to get rid of that annoying blank space in front of names with no
title
element:
xsl:if test=nametitle xsl:value-of select=nametitle
xsl:text xsl:text xsl:if
page 108
Now our output is perfect:
Ms. Natalie Attired 707 Breitling Way
Winter Harbor, ME 00218 Harry Backstayge
283 First Avenue Skunk Haven, MA 02718
Mary Backstayge 283 First Avenue
Skunk Haven, MA 02718 Mr. Chester Hasbrouck Frisby
1234 Main Street Sheboygan, WI 48392
Mary McGoon 103 Bryant Street
Boylston, VA 27318 Ms. Amanda Reckonwith
930-A Chestnut Street Lynn, MA 02930