Default Templates
Have you ever accidentally (or deliberately) applied an
empty stylesheet to a document? For example, if we apply empty.xsl:
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"/>
to shortcatalog.xml, the result is:
<?xml
version="1.0" encoding="utf-8"?>
Designing
Distributed Applications
Stephen Mohr
May 1999
1-861002-27-0
$49.99
Professional ASP
3.0
Alex Homer
Brian Francis
David Sussman
October 1999
1-861002-61-0
$59.99
Although the stylesheet was empty, the output is not. The
reason for this is that XSLT, as we saw briefly in Chapter 2, contains some
default templates to match elements, attributes, and text nodes that are not
matched elsewhere.
The main templates in this category are:
<xsl:template match="*|/">
<xsl:apply-templates/>
</xsl:template>
<xsl:template
match="text()|@*">
<xsl:value-of select="."/>
</xsl:template>
The first of these matches
the document root and all elements. In both cases, it causes processing to
continue by applying an <xsl:apply-templates> instruction to all child nodes. This means that,
if you have a template matching an element buried deep in your source tree, but
no template for one or more of its ancestors, the default template will cause
processing to continue until that element is reached.
The second template matches text nodes and all attributes,
causing the values of these to be output.
The combination of the first template, ensuring that the
document root and all elements are processed, and the second, ensuring that all
the text is copied to the result tree, is what generated our output.
There are also default templates
for comments, processing instructions and namespace nodes, each saying "do
nothing". Finally, in Chapter 4, we will meet another default template
covering the mode
attribute, which we have not met in detail yet.
Remember that these are only defaults. If you define your
own templates, they will over-ride these. It could be that you are only
processing a few elements in a document and don't want others processed. In
this case, including the following line in your stylesheet will ensure that
this happens:
<xsl:template match="*"/>
Template Match Conflicts
When several templates match the same source node, the XSLT
processor needs rules for choosing which template to use. In fact, because of
the existence of the default templates, every stylesheet will contain multiple
rules matching any node.
Luckily, XSLT provides a clear set of rules for deciding which template to use.
We will see in Chapter 5 that one stylesheet can import
another. If there is a conflict over which rule to apply when one belongs to
the importing stylesheet and one to an imported stylesheet, the rule in the
importing stylesheet is said to have to higher precedence,
and will be
the rule applied. If the conflict is between rules in imported stylesheets,
then stylesheets imported later have higher precedence than those imported
earlier. Of course, imported stylesheets can import other stylesheets. If you
get into this situation, the recommendation handles all cases using the concept
of an import
tree. Refer to the XSLT Recommendation itself to understand this.
The default rules are treated as though they were imported
before the stylesheet itself, and so have the lowest possible import
precedence.
Template rules can also have a priority
assigned. We saw how to do this earlier, when discussing the <xsl:template>
element. Where a priority is not assigned, a default priority value is used.
These default priorities are in the range -0.5 to 0.5. In general, the more
specific the match
expression, the higher the priority.
If there is still a conflict after applying the precedence
rules, the rule with the highest priority is applied.
It is possible that there will still be a conflict after the
priority rules have been applied. This is treated as an error. The stylesheet
processor will either indicate this error in some way or choose the last rule
in the stylesheet that matches the pattern.