我对XSLT apply-template语句感到困惑.例如,在w3school.
http://www.w3schools.com/xsl/xsl_apply_templates.asp
对于陈述,
<xsl:template match="/">
<html>
<body>
<h2>My CD Collection</h2>
<xsl:apply-templates/>
</body>
</html>
</xsl:template>
Run Code Online (Sandbox Code Playgroud)
我的困惑是,
(1)功能是<xsl:apply-templates/>什么?它不包含任何要调用的特定模板.我认为它会匹配(返回)当前元素的所有直接子节点(当前节点的非直接子节点不会被返回,当前节点是根节点),不确定我是否正确?
(2)在(1)中返回所有匹配的节点之后,XSLT处理器将做的下一步是什么?
(3)在这个特定的样本中,根节点是目录还是另一个更高级别的根?为什么?
乔治,提前谢谢
Rob*_*ney 50
有些事情可以让您更轻松地理解答案:
首先,节点和元素不是一回事.元素是节点,但节点不一定是元素.您经常会发现人们可以互换使用这些术语.XML中实际上有四种节点:元素,文本节点,处理指令和注释.(属性不是真正的节点,我将在一秒钟内完成.)
在XSLT中,XML文档的根不是它的顶级元素; 根是一个实际上并不存在的抽象.顶级元素是根的子元素.例如,这是一个格式良好的XML文档,其根目录有五个子节点,包括顶级元素:
<?xml-stylesheet href="mystyle.css" type="text/css"?>
<!-- this is a perfectly legitimate XML document -->
<top_level_element/>
Run Code Online (Sandbox Code Playgroud)
五?看起来只有三个.我想我会让你弄明白其他两个是你自己.提示:在该示例中实际上可能有七个节点.
XPath表达式/查找文档根目录,而不是顶级元素.在上面的例子中,要查找顶级元素,您可以使用/top_level_element或/*.(/*用于查找顶级元素总是安全的,因为文档根目录必须具有单个元素子元素.)
因此,掌握了这些知识,让我们来看看它是什么apply-templates.它基本上执行两个步骤:首先,它构建一组节点.然后,对于每一个,它找到匹配的模板(从XSLT文件中的模板中)并将模板应用于它.正如您在其中一条评论中所观察到的那样,它在概念上非常类似于循环.
该select属性在第一步中使用.它提供了一个XPath表达式,用于构建将要应用模板的节点集.如果未select提供任何属性,则它构建的列表是上下文节点的所有子项.("上下文节点"是当前模板应用于的节点.)
元素的match属性在template第二步中使用.样式表处理器查找其match属性与其尝试应用模板的节点匹配的所有模板.如果它找到多个,它会选择最具体的一个,例如给出这些模板:
<xsl:template match="*"/>
<xsl:template match="foo"/>
<xsl:template match="foo[bar]"/>
Run Code Online (Sandbox Code Playgroud)
一个foo与元件bar子元件将由第三相匹配,一个foo无元件bar将被第二相匹配,和一个baz元件将被第一匹配.(XSLT使用的实际方法在这里定义;实际上,我已经使用XSLT近十年了,我从来没有一次需要知道它是如何工作的,尽管它很有趣.)
如果没有找到匹配,它将使用内置的默认模板为节点的类型-基本上,你可以假设任何XSLT转换隐含地包含了这些模板:
<xsl:template match="*">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="text()">
<xsl:copy/>
</xsl:template>
<xsl:template match="processing-instruction() | comment() | @*"/>
Run Code Online (Sandbox Code Playgroud)
拥有所有这些知识,您现在可以理解身份变换:
<xsl:template match="node() | @*">
<xsl:copy>
<xsl:apply-templates select="node() | @*"/>
</xsl:copy>
</xsl:template>
Run Code Online (Sandbox Code Playgroud)
这匹配任何节点或属性(请注意,属性不是节点,这就是@*需要的原因),复制它,然后将模板应用于其所有子节点和属性.(只有文档根和元素将具有子节点,并且只有元素将具有属性.)因为它是变换中唯一的模板,并且它匹配所有节点和属性,所以它将自身应用于所有子节点和属性.因此,它将源树中的所有内容复制到输出树.
如果将此模板添加到标识转换:
<xsl:template match="foo"/>
Run Code Online (Sandbox Code Playgroud)
你现在有一个转换,它复制源树中除了 foo元素之外的每个节点- 第二个模板匹配foo元素(第一个模板也匹配,但由于第二个match属性更具体,它是XSLT选择的一个)并且对它们不做任何处理.
鉴于这一切,您的具体问题的答案:
<xsl:apply-templates> 将模板应用于上下文节点的子节点.
匹配的节点不会在步骤1中"返回"; XSLT处理器为每个模板找到一个模板并应用它.
在此示例中,上下文节点是文档根,是顶级元素及其外部的任何注释或处理指令是子级的抽象节点.
| 归档时间: |
|
| 查看次数: |
16363 次 |
| 最近记录: |