Hack 31 Understand the Anatomy of an XSLT Stylesheet

figs/moderate.gif figs/hack31.gif

You had a close brush with XSLT in the hack that discussed converting text to XML [Hack #18], but you didn't see much more than the stylesheet's name. Here is the complete stylesheet, time.xsl:

<xsl:stylesheet version="1.0" 

 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

   

<xsl:template match="Import">

 <xsl:apply-templates select="Row"/>

</xsl:template>

   

<xsl:template match="Row">

 <time timezone="{@timezone}">

  <xsl:copy-of select="hour|minute|second"/>

  <xsl:apply-templates select="atomic"/>

 </time>

</xsl:template>

   

<xsl:template match="atomic">

 <xsl:copy>

  <xsl:attribute name="signal">true</xsl:attribute>

 </xsl:copy>

</xsl:template>

   

</xsl:stylesheet>

3.2.1 The Document Element

An XSLT stylesheet has two possible document elements, stylesheet and transform (see line 1). Both have identical attributes; in fact, the only difference between the two is that they have different names, but stylesheet seems more popular with developers than transform.

The version attribute is required. Some XSLT processors support a value of 1.1 or 2.0, in support of those versions of the XSLT specs, but 1.0 is the most commonly used value. (Version 1.1 of XSLT is not and will never be a W3C recommendation, so any support for it is processor-dependent.) The namespace declaration is also required if you want an XSLT processor to recognize the XSLT markup. The namespace name for XSLT 1.0 is http://www.w3.org/1999/XSL/Transform. The prefix xsl is conventional: you can't get very far with XSLT without using a namespace prefix. Believe me, I've tried.

3.2.2 Templates

Templates are at the heart of what XSLT does. Templates match nodes in the document being processed, and when a node is matched, the content of the template is instantiated or executed. Nodes are the building blocks of an XML document. According to the XPath 1.0 data model (http://www.w3.org/TR/xpath#data-model), seven nodes are identifiable within an XML document: root, element, attribute, text, comment, processing instruction, and namespace nodes.

XSLT has some built-in templates that are instantiated in the absence of matched templates. In other words, if nodes are matched but no templates are found for a processed document, built-in templates will automatically be instantiated, returning text nodes, among other things.

3.2.2.1 Using apply-templates

This stylesheet has three templates (lines 3, 7, and 14). The first template matches the element Import, the document element of a converted text document in xmlspy (see [Hack #18] ). When an apply-templates element is encountered, it processes all the children of the matched node. If apply-templates has a select attribute, it processes only the selected nodes. The apply-templates element on line 4 attempts to find other templates in the stylesheet that match the Row element, the child of Import.

3.2.2.2 A literal result element

The template beginning on line 7 matches the Row element. When found, the template is instantiated: a literal result element time is output to the result tree, with a timezone attribute taking its value from an attribute in the source tree. A literal result element is output literally (appearing directly in the result), and is subject to a well-formedness check by the processor, as is the entire stylesheet.

3.2.2.3 The attribute value template

The braces on line 8 hold something called an attribute value template. This is sort of a template within a template. When the XSLT processor encounters a timezone attribute in the source tree, it grabs the value held by the attribute and places it in the value of the attribute represented in the stylesheet.

3.2.2.4 The copy-of and copy elements

Line 9 contains a copy-of element that makes copies of the hour, minute, and second nodes in the result tree. apply-templates (line 10) searches for a template matching atomic elements. copy-of makes deep copies of elements, copying attributes if present.

When the template on line 14 matches an atomic element, it makes a copy of the element with the copy element, adding a signal attribute (line 16) to it in the output using an attribute instruction element (there are instruction elements for elements, attributes, comments, and more). copy makes a shallow copy of a node, leaving attribute nodes behind.