I have several templates that match various nodes in an xml document. If I do just an
<xsl:apply-templates/> it somehow recursively outputs the text of all the nodes beneath. I just want it to recursively match any template I have defined. How do I do that ?
The <xsl:template> element is used to build templates. The match attribute is used to associate a template with an XML element. The match attribute can also be used to define a template for the entire XML document. The value of the match attribute is an XPath expression (i.e. match="/" defines the whole document).
The <xsl:apply-templates> element applies a template to the current element or to the current element's child nodes. If we add a "select" attribute to the <xsl:apply-templates> element, it will process only the child elements that matches the value of the attribute.
XSLT apply-templates define how to find elements and help in removing unwanted text in the document. It applies a template rule to the current child nodes. It adds a select attribute along with the template to specify the order of child nodes to process the current task with the help of the XSLT processor.
The XPath expression @* | node() selects the union of attribute nodes ( @* ) and all other types of XML nodes ( node() ). It is a shorthand for attribute::* | child::node() .
This is happening because of the built-in templates in XSLT. XSLT has a couple of built in templates, which say:
- when you apply templates to an element, process its child elements
- when you apply templates to a text node, give its value
Together, it means that if you apply templates to an element but don't have an explicit template for that element, then its content gets processed and eventually you end up with the text that the element contains.
Read the full explanation here: http://www.dpawson.co.uk/xsl/sect2/defaultrule.html
You can override the default templates for text nodes by defining your own template and have it do nothing.
<xsl:template match="text()" />
This is probably the most frequent problem even experienced XSLT programmers experience.
The observed behavior is exactly how an XSLT-compliant processor shoud behave.
Take into account that:
<xsl:apply-templates/>
is an abbreviation for:
<xsl:apply-templates select="child::node()"/>
and the existence of the built-in template rules. According to the XSLT 1.0 Spec.:
"5.8 Built-in Template Rules
There is a built-in template rule to allow recursive processing to continue in the absence of a successful pattern match by an explicit template rule in the stylesheet. This template rule applies to both element nodes and the root node. The following shows the equivalent of the built-in template rule:
<xsl:template match="*|/"> <xsl:apply-templates/> </xsl:template>
There is also a built-in template rule for each mode, which allows recursive processing to continue in the same mode in the absence of a successful pattern match by an explicit template rule in the stylesheet. This template rule applies to both element nodes and the root node. The following shows the equivalent of the built-in template rule for mode m.
<xsl:template match="*|/" mode="m"> <xsl:apply-templates mode="m"/> </xsl:template>
There is also a built-in template rule for text and attribute nodes that copies text through:
<xsl:template match="text()|@*"> <xsl:value-of select="."/> </xsl:template>
The built-in template rule for processing instructions and comments is to do nothing.
<xsl:template match="processing-instruction()|comment()"/>
The built-in template rule for namespace nodes is also to do nothing. There is no pattern that can match a namespace node; so, the built-in template rule is the only template rule that is applied for namespace nodes.
The built-in template rules are treated as if they were imported implicitly before the stylesheet and so have lower import precedence than all other template rules. Thus, the author can override a built-in template rule by including an explicit template rule "
--- End of XSLT Spec quote ---
So, if the author wants to be in full control of the XSLT processing, they should override all built-in templates.
For example, if we do not want text()
nodes to be copied to the output, we can cause them to be ignored by overriding the built-in template in the following way:
<xsl:template match="text()" />
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With