简体   繁体   中英

<apply-templates/> vs <apply-templates select=“…”/> in XSLT

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>

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM