Fortunately, you can make the transformation much simpler by using matched templates
. A matched template is one the XSLT processor triggers when its "match" attribute matches the current (context) node, whether that's simply the name of a tag or a more complex XPath expression. For example, the processor will trigger the following template whenever the context node is a "lang" attribute (the ampersand denotes an attribute node rather than an element node).
<xsl:text>This element has the follwing language id:<xsl:value-of select="@lang"></xsl:text>
By processing the file through matched templates, the code makes as few assumptions as possible about the format of the input file. For example, the following stylesheet outputs exactly the same result for both input files, even though their hierarchical formats differ significantly. Here's the revised stylesheet:
<xsl:output indent="yes" encoding="utf-8"/>
This event-driven version matches the root elementregardless of its nameby using the single backslash (/
) syntax. Next, it outputs the root <titles>
tag, and instructs the stylesheet to continue the iteration over the contents of the current or context
node (the root node in this case) with the apply-templates
If you apply this stylesheet to the second input file, you'll get the following result:
<title>Photoshop 6 for Professionals</title>
The output is indeed the same as for the first input file, except for one minor annoyance. There are some gratuitous carriage returns before and after the <title>
tags that cause the extra white space in the output.
After trying to determine the cause of these extra carriage returns, an occasional XSLT programmer might just drop the simple event-driven approach altogether in favor of the more complex flow-driven one. But if you instead explore the XSLT specification
, you'll find a built-in template
that copies text through and thus outputs the carriage returns:
In the example above, the carriage returns stem from the inside of the <section>
, and <book>
tags of the input document, one for each tag.
To correct that, you can add one line to the event-driven stylesheet that matches text()
nodes as follows:
That line gets rid of the carriage returns by overriding the built-in text template using a custom version that produces no output.
The key point to take away here is that almost any useful XSLT stylesheet should override at least two of the built-in templates
: the one for text, shown above, and the one that matches all nodes, which is:
The built-in template for nodes copies nothing to the output, but by invoking the <xsl:apply-templates/>
call, allows other templates to match children of the current tag. In other words, any XSLT stylesheet processes all the nodes in the input document by default
|Author's Note: You can gain fine-grained control over extra whitespace characters in the XSLT output by using the <xsl:preserve-space> and <xsl:strip-space> constructs in the stylesheet, or by using the xml:space attribute on XML tags in the input files.