Skip to content

Instantly share code, notes, and snippets.

@zamber
Last active December 17, 2015 03:59
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zamber/5547362 to your computer and use it in GitHub Desktop.
Save zamber/5547362 to your computer and use it in GitHub Desktop.
An example of Xalan XSLT 1.0 multi-pass processing of nodes with some nice sorting options (show empty nodes last, case insensitive sort). Load it up in your favorite editor (Intellij IDEA in my case) and play with it :D.
<bookstore>
<book>
<title lang="en">everyday Italian</title>
<author>Giada De Laurentiis</author>
<year>2005</year>
<price/>
</book>
<book>
<title lang="en">Harry Potter</title>
<author>J K. Rowling</author>
<year>2005</year>
<price>29</price>
</book>
<book >
<title lang="en">XQuery Kick Start</title>
<author>James McGovern</author>
<author>Per Bothner</author>
<author>Kurt Cagle</author>
<author>James Linn</author>
<author>Vaidyanathan Nagarajan</author>
<year>2003</year>
<price/>
</book>
<book>
<title lang="en">Learning XML</title>
<author>Erik T. Ray</author>
<year>2003</year>
<price>39</price>
</book>
<book>
<title lang="en">Learning XML</title>
<author>Erik T. Ray</author>
<year>2003</year>
<price/>
</book>
</bookstore>
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exslt="http://exslt.org/common"
exclude-result-prefixes="exslt">
<!-- Set to yes and comment out strip-space for pretty editor output -->
<xsl:output indent="yes" method="html"/>
<!-- Strips whitespace for all elements -->
<xsl:strip-space elements="*"/>
<!-- README: This is a useful XSLT example of multi-pass processing of whole node sets and some
advanced node ordering -->
<!-- just the basic html structure, move to the 'processing' template for the fun stuff -->
<xsl:template match="/">
<html>
<body>
<h2>Books</h2>
<table border="1">
<tr>
<th>Price</th>
<th>Title</th>
</tr>
<xsl:call-template name="processing"/>
</table>
</body>
</html>
</xsl:template>
<xsl:template name="processing">
<xsl:variable name="lowercase" select="'abcdefghijklmnopqrstuvwxyz'" />
<xsl:variable name="uppercase" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'" />
<!-- Here we are loading some nodes to a variable to get a Result Tree Fragment -->
<xsl:variable name="RTF">
<xsl:for-each select="//book">
<!-- Sort by price. Elements without a price get a price of 100000 to be shown last -->
<xsl:sort
select="concat(substring('100000',1,6*not(boolean(price/text()))), price/text() )"
data-type="number" order="ascending"/>
<!-- Another sort for alphabetical order of priceless ;) books. Note that it's
case-sensitive -->
<xsl:sort select="title" data-type="text" order="ascending" />
<!-- This sort is not case-sensitive. Use this one or the former as you need. -->
<xsl:sort select="translate(title, $lowercase, $uppercase)"
data-type="text" order="ascending"/>
<!-- Here we can also use <xsl:copy> for adding new nodes if we need the output to be
structured differently -->
<xsl:copy-of select="."/>
</xsl:for-each>
</xsl:variable>
<!-- Now we take the RTF and convert it to a node-set so we can process it yet again! -->
<xsl:variable name="set" select="exslt:node-set($RTF)"/>
<!-- Go and play with the new set -->
<xsl:for-each select="$set/book[position()&lt;3]">
<tr>
<td><xsl:value-of select="price"/></td>
<td><xsl:value-of select="title"/></td>
</tr>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment