There are seven kinds of nodes in an XML document: the root node, element nodes, attribute nodes, text nodes, comment nodes, processing instruction nodes, and namespace nodes. XSLT provides a default built-in template rule for each of these seven kinds of nodes that says what to do with that node if the stylesheet author has not provided more specific instructions. These rules use special wildcard patterns to match all nodes of a given type. Together these template rules have major effects on which nodes are activated when.
8.7.1 The Default Template Rule for Text and Attribute Nodes
The most basic built-in template rule copies the value of text and attribute nodes into the output document. It looks like this:
<xsl:template match="text( )@*"> <xsl:value-of select="."/> </xsl:template>
The text( ) node test is a pattern matching all text nodes, just as first_name is a pattern matching all first_name element nodes. @* is a pattern matching all attribute nodes. The vertical bar combines these two patterns so that the template rule matches both text and attribute nodes. The rule's template says that whenever a text or attribute node is matched, the processor should output the value of that node. For a text node, this value is simply the text in the node. For an attribute, this value is the attribute value but not the name .
Example 8-10 is an XSLT stylesheet that pulls the birth and death dates out of the born and died attributes in Example 8-1. The default template rule for attributes takes the value of the attributes, but an explicit rule selects those values. The @ sign in @born and @died indicates that these are attributes of the matched element rather than child elements.
Example 8-10. An XSLT stylesheet that reads born and died attributes
<?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="people"> <html> <head><title>Famous Scientists</title></head> <body> <dl> <xsl:apply-templates/> </dl> </body> </html> </xsl:template> <xsl:template match="person"> <dt><xsl:apply-templates select="name"/></dt> <dd><ul> <li>Born: <xsl:apply-templates select="@born"/></li> <li>Died: <xsl:apply-templates select="@died"/></li> </ul></dd> </xsl:template> </xsl:stylesheet>
When an XSLT processor applies this stylesheet to Example 8-1, it outputs the HTML document shown in Example 8-11.
Example 8-11. The HTML produced by applying Example 8-10 to Example 8-1
<html> <head> <title>Famous Scientists</title> </head> <body> <dl> <dt> Alan Turing </dt> <dd> <ul> <li>Born: 1912</li> <li>Died: 1954</li> </ul> </dd> <dt> Richard P Feynman </dt> <dd> <ul> <li>Born: 1918</li> <li>Died: 1988</li> </ul> </dd> </dl> </body> </html>
It's important to note that although this template rule says what should happen when an attribute node is reached, by default, the XSLT processor never reaches attribute nodes and, therefore, never outputs the value of an attribute. Attribute values are output according to this template only if a specific rule applies templates to them, and none of the default rules do this because attributes are not considered to be children of their parents. In other words, if element E has an attribute A , then E is the parent of A , but A is not the child of E . (The biological metaphor breaks down here.) Applying templates to the children of an element with <xsl:apply-templates/> does not apply templates to attributes of the element. To do that, the xsl:apply-templates element must have a match pattern specifically selecting attributes.
8.7.2 The Default Template Rule for Element and Root Nodes
The most important template rule is the one that guarantees that children are processed . Here is that rule:
<xsl:template match="*/"> <xsl:apply-templates/> </xsl:template>
The asterisk * is an XPath wildcard that matches all element nodes, regardless of what name they have or what namespace they're in. The forward slash / is an XPath expression that matches the root node. This is the first node the processor selects for processing, and, therefore, this is the first template rule the processor executes (unless a nondefault template rule also matches the root node). Again, the vertical bar combines these two expressions so that the rule matches both the root node and element nodes. In isolation, this rule means that the XSLT processor eventually finds and applies templates to all nodes except attribute and namespace nodes because every nonattribute, non-namespace node is either the root node, a child of the root node, or a child of an element. Only attribute and namespace nodes are not children of their parents. (You can think of them as disinherited nodes.)
Of course, templates may override the default behavior. For example, when you include a template rule matching person elements in your stylesheet, then children of the matched person elements are not necessarily processed, unless one of your own template rules says to process them.
8.7.3 The Default Template Rule for Comment and Processing Instruction Nodes
This is the default template rule for comments and processing instructions:
<xsl:template match="processing-instruction( )comment( )"/>
It matches all comments and processing instructions. However, it does not output anything into the result tree. That is, unless a stylesheet provides specific rules matching comments or processing instructions, no part of these items will be copied from the input document to the output document.
8.7.4 The Default Template Rule for Namespace Nodes
A similar template rule matches namespace nodes and instructs the processor not to copy any part of the namespace node to the output. This is truly a built-in rule that must be implemented in the XSLT processor's source code; it can't even be written down in an XSLT stylesheet because there's no such thing as an XPath pattern matching a namespace node. That is, there's no namespace( ) node test in XPath. The XSLT processor inserts any necessary namespace declarations in the output document automatically, without any special assistance from namespace templates.