I'm sure that this is an extremely basic question but here goes anyway! I have read that the built in template rule for text and attribute nodes in XSLT is
<xsl:template match="text()|@*">
<xsl:value-of select="."/>
</xsl:template>
However for the source document
<?xml version="1.0"?>
<booker>
<award>
<author blah="test">Aravind Adiga</author>
<title>The White Tiger</title>
<year>2008</year>
</award>
</booker>
And XSLT
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
</xsl:stylesheet>
I get the following output applying the transform in Visual Studio. Can someone please explain why I don't see "test" in the output?
Aravind Adiga
The White Tiger
2008
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).
Attributes can be added or modified during transformation by placing the <xsl:attribute> element within elements that generate output, such as the <xsl:copy> element. Note that <xsl:attribute> can be used directly on output elements and not only in conjunction with <xsl:element> .
With <xsl:apply-templates> the current node moves on with every iteration, whereas <xsl:call-template> does not change the current node.
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.
Because the built-in rule for elements does not apply templates to an element's own attributes, only to it's child elements. If you want to traverse the attributes in the same way you traverse the child elements (which is probably an artificial task) you need to define your own default:
<xsl:template match="*">
<xsl:apply-templates select="@*"/>
<xsl:apply-templates/>
</xsl:template>
To address this question from a comment:
Thanks, I don't need to actually do it, I'm just trying to understand the rules. So basically the @* part of the built in rule will never get invoked unless it is called explicitly?
In this case, there are two default rules which interest us:
<xsl:template match="text()|@*">
<xsl:value-of select="."/>
</xsl:template>
<xsl:template match="/|*">
<xsl:apply-templates/>
</xsl:template>
When the document is processed, the second template matches the root and applies-templates. The default for apply-templates is to select all child nodes (attributes, confusingly, aren't child nodes). You never select any attribute to be processed, as the only apply-templates
appears in it's default form.
So if you selected somewhere any attribute (like Vincent Marchetti did), it would be processed by the first mentioned default template.
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