Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

XSLT Built-in Template Rules for attributes

Tags:

xslt

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

like image 885
Martin Smith Avatar asked May 14 '10 15:05

Martin Smith


People also ask

Which of the following is the correct way to build a template in XSLT?

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

What is one way to add an attribute to an element in XSLT?

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

What is the difference between call template and apply template in XSLT?

With <xsl:apply-templates> the current node moves on with every iteration, whereas <xsl:call-template> does not change the current node.

What is apply templates 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.


2 Answers

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>
like image 158
Vincent Marchetti Avatar answered Sep 19 '22 20:09

Vincent Marchetti


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.

like image 44
Krab Avatar answered Sep 23 '22 20:09

Krab