XSLT Transformations with JavaScript
- To transform XML documents with XSLT using JavaScript.
- To work with the sarissa.js library to make XSLT transformations less painful.
- To use XSLT in an Ajax application.
XSLT
XSLT documents are valid XML documents that describe how another XML document should be transformed. For XSLT to work, it needs an XML document to transform and an engine to make the transformation take place. In addition, parameters can be passed in to XSLTs providing further instructions on how to do the transformation.
The diagram below shows how this all works.
Basic XSLT
This lesson does not get into the details of the XSLT language. However, to get the idea of how it works, we'll take a look at a simple XML document and an XSLT stylesheet, which is used to transform the XML to HTML. Then we will look at how the browsers handle XSLT transformations.
Code Sample: XSLT/Demos/Paul.xml
<?xml version="1.0"?> <?xml-stylesheet href="Beatle.xsl" type="text/xsl"?> <person> <name> <firstname>Paul</firstname> <lastname>McCartney</lastname> </name> <job>Singer</job> <gender>Male</gender> </person>
This is a straightforward XML document. The processing instruction at the top indicates that the XML document should be transformed using Beatle.xsl (shown below).
Code Sample: XSLT/Demos/Beatle.xsl
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html"/>
<xsl:template match="child::person">
<html>
<head>
<title>
<xsl:value-of select="descendant::firstname" />
<xsl:text> </xsl:text>
<xsl:value-of select="descendant::lastname" />
</title>
</head>
<body>
<xsl:value-of select="descendant::firstname" />
<xsl:text> </xsl:text>
<xsl:value-of select="descendant::lastname" />
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Note that the document begins with an XML declaration. This is because XSLTs are XML documents themselves.
The second line is the document element of the XSLT. It states that this document is a version 1.0 XSLT document.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">The third line (<xsl:output method="html"/>) indicates that the resulting output will be HTML.
The fourth line is an open <xsl:template> element. The match attribute of this tag takes an XPath, which indicates that this template applies to the person node of the XML document. Because person is the document element, this template will only run once.
There are then a few lines of HTML followed by two <xsl:value-of /> elements separated by one <xsl:text> element. The <xsl:value-of /> tag has a select attribute, which takes an XPath pointing to a specific element or group of elements within the XML document. In this case, the two <xsl:value-of /> tags point to firstname and lastname elements, indicating that they should be output in the title of the HTML page. The <xsl:text> element is used to create a space between the first name and the last name elements.
<xsl:value-of select="descendant::firstname" /> <xsl:text> </xsl:text> <xsl:value-of select="descendant::lastname" />There are then some more HTML tags followed by the same XSLT tags, re-outputting the first and last name of the Beatle in the body of the HTML page. The output looks like this:
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Paul McCartney</title> </head> <body>Paul McCartney</body> </html>
XSLT in the Browser
Unfortunately, XSLT transformations are handled differently by different browsers. We will see how they are handled by Internet Explorer and Mozilla and then will look at a library that makes cross-browser XSLT simple. First, a look at the documents:
The XML
Code Sample: XSLT/Demos/Beatles.xml
<?xml version="1.0"?> <?xml-stylesheet href="Beatles.xsl" type="text/xsl"?> <beatles> <beatle link="http://www.paulmccartney.com"> <name> <firstname>Paul</firstname> <lastname>McCartney</lastname> </name> </beatle> <beatle link="http://www.johnlennon.com"> <name> <firstname>John</firstname> <lastname>Lennon</lastname> </name> </beatle> <beatle link="http://www.georgeharrison.com"> <name> <firstname>George</firstname> <lastname>Harrison</lastname> </name> </beatle> <beatle link="http://www.ringostarr.com"> <name> <firstname>Ringo</firstname> <lastname>Starr</lastname> </name> </beatle> </beatles>
The XSLT
Code Sample: XSLT/Demos/Beatles.xsl
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<table border="1">
<xsl:for-each select="beatles/beatle">
<xsl:sort select="name/lastname"/>
<tr>
<td><a href="{@link}"><xsl:value-of select="name/lastname"/></a></td>
<td><a href="{@link}"><xsl:value-of select="name/firstname"/></a></td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
The Output
Code Sample: XSLT/Demos/Beatles.html
<table border="1"> <tr> <td> <a href="http://www.georgeharrison.com">Harrison</a> </td> <td> <a href="http://www.georgeharrison.com">George</a> </td> </tr> <tr> <td> <a href="http://www.johnlennon.com">Lennon</a> </td> <td> <a href="http://www.johnlennon.com">John</a> </td> </tr> <tr> <td> <a href="http://www.paulmccartney.com">McCartney</a> </td> <td> <a href="http://www.paulmccartney.com">Paul</a> </td> </tr> <tr> <td> <a href="http://www.ringostarr.com">Starr</a> </td> <td> <a href="http://www.ringostarr.com">Ringo</a> </td> </tr> </table>
XSLT in Internet Explorer
The steps for doing an XSLT transformation in Internet Explorer are as follows:
- Load the XML document and XSLT document into XML DOM objects using ActiveX.
var xml = new ActiveXObject("Microsoft.XMLDOM"); var xslt = new ActiveXObject("Microsoft.XMLDOM"); - Set the async property on both documents to false so that they both completely load before any further processing is attempted.
xml.async = false; xslt.async = false;
- Load XML and XSLT documents into the XML DOM objects.
xml.load("Beatles.xml"); xslt.load("Beatles.xsl"); - Transform the XML to a string with the transformNode() method.
var output = xml.transformNode(xslt);
- The result can then be output to the innerHTML property of any element on the page.
var outputDiv = document.getElementById("Output"); outputDiv.innerHTML = output;
This code shown above is in XSLT/Demos/Xslt-IE.html.
XSLT in Mozilla
XSLT transformations in Mozilla are a bit more involved:
- Load the XML document and XSLT document into XML DOM objects using document.implementation.createDocument().
var xml = document.implementation.createDocument("", "", null); var xslt = document.implementation.createDocument("", "", null); - Set the async property on both documents to false so that they both completely load before any further processing is attempted.
xml.async = false; xslt.async = false;
- Load XML and XSLT documents into the XML DOM objects.
xml.load("Beatles.xml"); xslt.load("Beatles.xsl"); - Create a new XSLTProcessor object and use its importStylesheet() method to import the XSLT DOM object.
var processor = new XSLTProcessor(); processor.importStylesheet(xslt);
- Transform the XML to a new XML DOM object with the transformToDocument() method of the XSLTProcessor.
var XmlDom = processor.transformToDocument(xml)
- Create a new XMLSerializer and use it to serialize the new XML DOM object to a string.
var serializer = new XMLSerializer(); var output = serializer.serializeToString(XmlDom.documentElement);
- The result can then be output to the innerHTML property of any element on the page.
var outputDiv = document.getElementById("Output"); outputDiv.innerHTML = output;
This code shown above is in XSLT/Demos/Xslt-FF.html.
Sarissa
Sarissa is a JavaScript library (available at http://sarissa.sourceforge.net) that provides a cross-browser wrapper for XML APIs. In addition to XSLT transformations, the Sarissa library provides cross-browser methods for instantiating Document objects, loading XML from files and XML strings, and handling XPath queries.
The great thing about using Sarissa for XSLT transformations is that you don't have to learn yet a new API. Sarissa emulates Mozilla's API for Internet Explorer so that we can use to Mozilla method described above for cross-browser development. All we need to do is include the sarissa.js library and then use Sarissa's getDomDocument() method to create the XML and XSLT DOM objects. The file is shown below.
Code Sample: XSLT/Demos/Xslt-sarissa.html
<html>
<head>
<script type="text/javascript" src="../../sarissa.js"></script>
<script type="text/javascript">
function XsltTransform()
{
var xml = Sarissa.getDomDocument();
var xslt = Sarissa.getDomDocument();
xml.async = false;
xslt.async = false;
xml.load("Beatles.xml");
xslt.load("Beatles.xsl");
var processor = new XSLTProcessor();
processor.importStylesheet(xslt);
var XmlDom = processor.transformToDocument(xml)
var serializer = new XMLSerializer();
var output = serializer.serializeToString(XmlDom.documentElement);
var outputDiv = document.getElementById("Output");
outputDiv.innerHTML = output;
}
</script>
<title>XSLT with Sarissa</title>
</head>
<body onload="XsltTransform();">
<div id="Output"></div>
</body>
</html>
Advantages and Disadvantages of XSLT in Ajax Applications
XSLT provides a very good standard method for transforming XML documents. Many developers find it easier to write XSLTs than to write DOM-manipulation JavaScript code.
The only real downside of XSLT is that it is a pretty complicated language. If you don't know it already, you may find that it's not easy to pick up without some serious studying.
XSLT Transformations with JavaScript Conclusion
In this lesson of the Ajax tutorial, you have learned how to transform XML documents with XSLT in the browser and seen how these transformations can be used inside of Ajax applications.
