The Solution: Using Stylesheets with XSLT
To translate from XML to HTML, we'll create a stylesheet document as the first step in using an XSLT transform. The file nmsDataStylesheet.xsl (included in the source.zip file for this article) contains the stylesheet—let's have a look at part of it in Listing 3.
Listing 3 The first few lines in the stylesheet
<?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" > <xsl:output method="html"/>
The first line in Listing 3 is the same as a standard XML document. The last line in Listing 3 indicates that HTML is generated by the XSLT transform. Listing 4 illustrates the next section of the stylesheet.
Listing 4 Processing the root XML element
<xsl:template match="/"> <html><body> <xsl:apply-templates/> </body></html> </xsl:template> <xsl:template match="/nodedata"> <nodedata align="center"> <xsl:apply-templates/> </nodedata> </xsl:template>
Listing 4 is the key to understanding the use of stylesheets. A stylesheet consists of a number of templates. Each such template is defined using the <xsl:template> tag. These tags allow us to match the incoming text against a specified pattern. We also have a tag (<xsl:text>) that allows for arbitrary text insertion in the output stream.
One last point before leaving Listing 4. The last three lines illustrate the manner in which the topmost element (nodedata) is processed. Basically, as mentioned earlier, we're using templates to match the incoming XML data. (For more details on the internal operations of XSLT and stylesheets, see Sun's J2EE 1.4 tutorial.)
Listing 5 shows how we process the contact information. Line 1 indicates our hierarchical position in the XML file (refer to Listing 1). As shown in Listing 5, we're looking at the contact details just under the nodedata element.
Listing 5 Processing an XML node
<xsl:template match="/nodedata/contact"> <h1> <xsl:text>Contact: </xsl:text> <xsl:apply-templates select="text()"/> <xsl:apply-templates select="contact"/></h1> </xsl:template>
So what do we want to do at this point in the parsing process? Well, the first thing is to generate some useful text for the HTML output. In this case, we want to see the word Contact in the HTML file. To achieve this objective, we need to use the <xsl:text> tag mentioned earlier. This tag serves to write the text Contact: into the output stream ahead of the contact details. We'll see the following in the HTML stream:
<h1>Contact: Stephen Morris</h1>
This is rendered by the browser as a heading containing the text delimited by the <h1> tags. Each of the remaining XML tags will be processed in the same fashion.
Listing 6 demonstrates the way we process the element that contains the email contact details.
Listing 6 Processing the email XML node
<xsl:template match="/nodedata/email"> <h2> <xsl:text>Email: </xsl:text> <xsl:apply-templates select="text()"/> <xsl:apply-templates select="email"/></h2> </xsl:template>
The remaining nodes are handled in the same way and are not shown here. Listing 7 shows the tags used to round off the stylesheet.
Listing 7 The final tags
<xsl:template match="text()"> <xsl:value-of select="normalize-space()"/> </xsl:template> </xsl:stylesheet>
The items in Listing 7 serve to strip out the whitespace generated during the parsing.
Let's take a look at the source code before running it.