<apply-templates/> 与 XSLT 中的 <apply-templates select="..."/>
<apply-templates/> vs <apply-templates select="..."/> in XSLT
查看地址 http://www.w3schools.com/xml/tryxslt.asp?xmlfile=cdcatalog&xsltfile=cdcatalog_apply 下的 XSLT 代码 ... 下面是这段代码的第一部分(对我的问题起决定作用的部分):
<?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:apply-templates/>
到
<xsl:apply-templates select="cd"/>
转换不再有效...(代码现在如下所示:)
<?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>
我的问题是:为什么更改会破坏代码?在我看来,这两种情况的逻辑是一样的:
- 应用模板匹配"cd"
- 内部模板 "cd" 应用其他两个模板 ("title" + "artist")
更新:
整个xslt代码如下:
<?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>
以下是 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>
W3C 学校没有告诉您的是关于 XSLT 的 Built-in Template Rules。
当您执行 <xsl:apply-templates select="cd"/>
时,您位于文档节点上,即 catalog
元素的 parent。执行 select="cd"
将 select 什么都没有,因为 cd
是 catalog
元素的 child,而不是文档节点本身的 child。只有 catalog
是 child.
(注意 catalog
是 XML 的 "root element"。一个 XML 文档只能有一个根元素。
但是,当您执行 <xsl:apply-templates />
时,这相当于 <xsl:apply-templates select="node()" />
,这将 select catalog
元素。这是 built-in 模板发挥作用的地方。您的 XSLT 中没有匹配 catalog
的模板,因此使用 built-in 模板。
<xsl:template match="*|/">
<xsl:apply-templates/>
</xsl:template>
(此处*
匹配任意元素)。因此,此 built-in 模板将 select catalog
的 child 节点,因此匹配 XSLT 中的其他模板。
请注意,在您的第二个示例中,您可以将模板匹配更改为此...
<xsl:template match="/*">
这将匹配 catalog
元素,因此 <xsl:apply-templates select="cd" />
将起作用。
查看地址 http://www.w3schools.com/xml/tryxslt.asp?xmlfile=cdcatalog&xsltfile=cdcatalog_apply 下的 XSLT 代码 ... 下面是这段代码的第一部分(对我的问题起决定作用的部分):
<?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:apply-templates/>
到
<xsl:apply-templates select="cd"/>
转换不再有效...(代码现在如下所示:)
<?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>
我的问题是:为什么更改会破坏代码?在我看来,这两种情况的逻辑是一样的:
- 应用模板匹配"cd"
- 内部模板 "cd" 应用其他两个模板 ("title" + "artist")
更新:
整个xslt代码如下:
<?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>
以下是 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>
W3C 学校没有告诉您的是关于 XSLT 的 Built-in Template Rules。
当您执行 <xsl:apply-templates select="cd"/>
时,您位于文档节点上,即 catalog
元素的 parent。执行 select="cd"
将 select 什么都没有,因为 cd
是 catalog
元素的 child,而不是文档节点本身的 child。只有 catalog
是 child.
(注意 catalog
是 XML 的 "root element"。一个 XML 文档只能有一个根元素。
但是,当您执行 <xsl:apply-templates />
时,这相当于 <xsl:apply-templates select="node()" />
,这将 select catalog
元素。这是 built-in 模板发挥作用的地方。您的 XSLT 中没有匹配 catalog
的模板,因此使用 built-in 模板。
<xsl:template match="*|/">
<xsl:apply-templates/>
</xsl:template>
(此处*
匹配任意元素)。因此,此 built-in 模板将 select catalog
的 child 节点,因此匹配 XSLT 中的其他模板。
请注意,在您的第二个示例中,您可以将模板匹配更改为此...
<xsl:template match="/*">
这将匹配 catalog
元素,因此 <xsl:apply-templates select="cd" />
将起作用。