Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can xsl:apply-templates match only templates I have defined?

Tags:

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 ?

like image 765
user43940 Avatar asked Dec 06 '08 15:12

user43940


People also ask

How does xsl template match work?

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).

How do I apply a template in XSLT?

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.

What is xsl apply templates select () />?

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.

What does @* mean in XSLT?

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() .


2 Answers

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()" /> 
like image 154
Mads Hansen Avatar answered Oct 11 '22 17:10

Mads Hansen


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()" />

like image 39
Dimitre Novatchev Avatar answered Oct 11 '22 18:10

Dimitre Novatchev