XSLT with Saxon

The Home Edition of Saxon is available free on SourceFourge for Java and .NET - and the Java version is my choice.

A typical usage of XLST is for transforming an internal XML data representation to a format more suitable for a client application.

Let's see an example. Say that we have an XML like this:
<?xml version="1.0" encoding="UTF-8"?>
<People>
<Person>
<Name>Winston Churchill</Name>
<Description>Winston Churchill was a mid 20th century British politician who
became famous as Prime Minister during the Second World War.</Description>
</Person>
<Person>
<Name>Indira Gandhi</Name>
<Description>Indira Gandhi was India’s first female prime minister
and was assassinated in 1984.</Description>
</Person>
<Person>
<Name>John F. Kennedy</Name>
<Description>JFK, as he was affectionately known, was a United States
president who was assassinated in Dallas, Texas.</Description>
</Person>
</People>

The root entity, People, contains a list of Person, each of them having a Name and a Description.

We want transform it to an HTML, so to show it to the user as a web page that should look in this way:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Information about 3 people.</title>
</head>
<body>
<h3>Winston Churchill</h3>
<p>Winston Churchill was a mid 20th century British politician who
became famous as Prime Minister during the Second World War.
</p>
<h3>Indira Gandhi</h3>
<p>Indira Gandhi was India’s first female prime minister
and was assassinated in 1984.
</p>
<h3>John F. Kennedy</h3>
<p>JFK, as he was affectionately known, was a United States
president who was assassinated in Dallas, Texas.
</p>
</body>
</html>

That's what XSLT is good at. What we have to do, it is writing a stylesheet saying how our XSLT processor has to generate the output. In our case, we want something like:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:template match="/">
<html>
<head>
<title>Information about <xsl:value-of select="count(/People/Person)"/> people.</title>
</head>
<body>
<xsl:apply-templates select="/People/Person"/>
</body>
</html>
</xsl:template>

<xsl:template match="Person">
<h3><xsl:value-of select="Name"/></h3>
<p><xsl:value-of select="Description"/></p>
</xsl:template>
</xsl:stylesheet>

Line 1: This document is an XML.
Line 2: Actually, it is an XLS stylesheet version 2.0, as defined by w3.org in 1999.
Line 3: We ask the processor to consider the root element.
Line 6: We call the function count() specifying the path of the objects that we want to count - in this case, the number of Persons under People - we assign the result to the select attribute of the xsl element value-of. And that's how we'll have the resulting value in the generated document.
Line 9: Sort of calling a function, or better, applying the template that is defined below, passing as parameter each found element /People/Person.
Line 14: Here is the template that we "call" from line 9, as input we expect a Person, and we use, putting them in the select attribute of an xsl value-of element, its Name and Description: the first in an HTML third-level header tag, the latter in a pragraph.

Having the input XML, the XLST transformation, we just have to call Saxon from command line to do the magic:
java -jar c:\dev\saxon\saxon9he.jar input.xml example.xslt -o:out.html
To make it run correctly the java\bin folder should be in your system path; you should explicitly give the path to the Saxon executable JAR (putting it in the CLASSPATH does not work); the input.xml and the example.xslt, as described above, are supposed to be in the current folder; and the result is sent to out.html, again in the current folder.

Remember to put a colon after the -o, otherwise you get the puzzling error message "Command line option -o requires a value".

More information on XSLT and Saxon in chapter eight of Beginning XML by David Hunter et al. (Wrox).

4 comments:

  1. Thank you for the tip about using a colon after the -o option. I was getting the "Command line option -o requires a value" error, and didn't know why.

    ReplyDelete
  2. ditto on Brent's earlier comment. You try and cram all this great information in a blog post, but these little nuggets like "don't forget the ":" turn out to be insanely valuable.

    ReplyDelete
    Replies
    1. As they say, the devil is in the details.

      Delete