I am trying to understand apply-templates
but I do not understand why I don't write any select="nodename" in the apply-templates
here: (I think of the first apply-templates beneath the My CD collection)
Snippet from the input document:
<?xml version="1.0" encoding="ISO-8859-1"?>
<catalog>
<cd>
<title>Empire Burlesque</title>
<artist>Bob Dylan</artist>
<country>USA</country>
<company>Columbia</company>
<price>10.90</price>
<year>1985</year>
</cd>
<cd>
<title>Hide your heart</title>
<artist>Bonnie Tyler</artist>
<country>UK</country>
<company>CBS Records</company>
<price>9.90</price>
<year>1988</year>
</cd>
<cd>
<title>Greatest Hits</title>
<artist>Dolly Parton</artist>
<country>USA</country>
<company>RCA</company>
<price>9.90</price>
<year>1982</year>
</cd>
XSLT:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<h2>My CD Collection</h2>
<xsl:apply-templates/>
</body>
</html>
</xsl:template>
<xsl:template match="cd">
<p>
<xsl:apply-templates select="title"/>
<xsl:apply-templates select="artist"/>
</p>
</xsl:template>
<xsl:template match="title">
Title: <span style="color:#ff0000">
<xsl:value-of select="."/></span>
<br />
</xsl:template>
<xsl:template match="artist">
Artist: <span style="color:#00ff00">
<xsl:value-of select="."/></span>
<br />
</xsl:template>
</xsl:stylesheet>
Taken from the w3schools tutorial. How does it understand which of the templates it should choose?
You can control processing order by specifying a select attribute on apply-templates . The first apply-templates calls the cd template each time an element named "cd" is encountered. The cd template, in turn calls the title and artist templates to process the children elements of <cd> .
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.
As by the specs:
In the absence of a select attribute, the xsl:apply-templates instruction processes all of the children of the current node, including text nodes.
apply-templates
without XPath selection, applies the templates following the hierarchy of the XML tree view built by the processor during compilation, unless you explicitly drives the templates (as you did for title
and artist
).
You might also want to think of how built-in template rules work. These rules run behind the scenes and allows recursive process go on in absence of a successful pattern match.
So if you omit the template match for the root /
your templates will get executed anyway, thanks to the built-in rules.
I think the processing order should be like this:
xsl:apply-templates
tells the processor to apply the templates to the catalog
element (in the place where it is invoked).catalog
, so that the built-in rule allows continue processing toward the other descendant elements (catalog
) until a new template with succesfull pattern match is found (cd
)The built-in rule runs behind the scenes and you must think always your transform as composed by your templates, plus a few additional hidden (but working) templates:
<xsl:template match="*|/">
<xsl:apply-templates />
</xsl:template>
<xsl:template match="text()|@*">
<xsl:value-of select="."/>
</xsl:template>
<xsl:template match="processing-instruction()|comment()"/>
In your specific case the former template among the three above was the one resonsible for applying templates to the cd
elements.
These built-in templates gets overridden each time you write an explicit template.
Examples
You can obtain the same by replacing:
<xsl:template match="cd">
<p>
<xsl:apply-templates select="title"/>
<xsl:apply-templates select="artist"/>
</p>
</xsl:template>
with:
<xsl:template match="country|company|price|year"/>
<xsl:template match="cd">
<p>
<xsl:apply-templates />
</p>
</xsl:template>
About the root, in your case, you could also obtain the same by replacing:
<xsl:template match="/">
<html>
<body>
<h2>My CD Collection</h2>
<xsl:apply-templates/>
</body>
</html>
</xsl:template>
with
<xsl:template match="/catalog">
<html>
<body>
<h2>My CD Collection</h2>
<xsl:apply-templates/>
</body>
</html>
</xsl:template>
or still:
<xsl:template match="/">
<html>
<body>
<h2>My CD Collection</h2>
<xsl:apply-templates select="catalog"/>
</body>
</html>
</xsl:template>
or still:
<xsl:template match="catalog">
<html>
<body>
<h2>My CD Collection</h2>
<xsl:apply-templates />
</body>
</html>
</xsl: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