0
votes

Look at the XSLT-code under the address http://www.w3schools.com/xml/tryxslt.asp?xmlfile=cdcatalog&xsltfile=cdcatalog_apply ... Below you find the first part of this code (and the one decisive for my question):

<?xml version="1.0" encoding="UTF-8"?>
<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>

If you now change only the line

<xsl:apply-templates/> 

to

<xsl:apply-templates select="cd"/>

the transformation does not work anymore ... (The code now looks as follows:)

<?xml version="1.0" encoding="UTF-8"?>
<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 select="cd"/>  <!--ONLY LINE OF CODE THAT WAS CHANGED-->
</body>
</html>
</xsl:template>

My question is: Why does the change break the code? In my opinion, the logic is the same in both cases:

  1. apply the template matching "cd"
  2. inside template "cd" apply the other two templates ("title" + "artist")

UPDATE:

The whole xslt code is as follows:

<?xml version="1.0" encoding="UTF-8"?>
<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>

Here's an excerpt from the xml:

<?xml version="1.0" encoding="UTF-8"?>
<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>
    ......
 </catalog>
1
Can you edit your question to include a sample of the XML, so this question can be "stand-alone" and doesn't rely on having to click through to W3Schools to see. Thanks!Tim C

1 Answers

5
votes

What W3C schools doesn't tell you is about XSLT's Built-in Template Rules.

When you do <xsl:apply-templates select="cd"/> you are positioned on the document node, which is the parent of the catalog element. Doing select="cd" will select nothing, because cd is a child of the catalog element, and not a child of the document node itself. Only catalog is a child.

(Note that catalog is the "root element" of the XML. An XML document can have only one root element).

However, when you do <xsl:apply-templates />, then this is equivalent to <xsl:apply-templates select="node()" /> which will select the catalog element. This is where the built-in templates kick in. You don't have a template matching catalog in your XSLT, and so the built-in one is used.

<xsl:template match="*|/">
   <xsl:apply-templates/>
</xsl:template>

(Here * matches any element). Thus, this built-in template will select the child nodes of catalog, and so match the other templates in your XSLT.

Note that, in your second example, you can change the template match to this...

<xsl:template match="/*">

This will match the catalog element, and so then <xsl:apply-templates select="cd" /> will work.