我想我知道答案,但我只想确认我正确理解这一点 .
当XSLT模板匹配并执行时,默认情况下不处理当前节点的子节点(执行匹配模板的节点当前节点) . 必须调用"apply-templates"才能使处理器遍历当前(匹配)节点的子节点 .
考虑这个XML:
<person>
<firstName>Deane</firstName>
<lastName>Barker</lastName>
</person>
在转换期间,XSLT处理器从“person”元素开始 . 如果它找到了一个模板,它将执行它,但不会下降到“firstName”和“lastName”元素来查找那些模板 . 只有在“person”模板中显式调用“apply-templates”时才会执行此操作 .
考虑一下这个XSL:
<!-- Template #1 -->
<xsl:template match="person">
I found a "person" element
</xsl:template>
<!-- Template #2 -->
<xsl:template match="firstName">
I found a "firstName" element
</xsl:template>
在这种情况下,模板#2将不会运行,对吗?遍历XML文档将触及“person”元素,找到Template#1,执行它,然后永远不会进入“person”的子元素 .
如果我将第一个模板更改为此 -
<!-- Template #1 -->
<xsl:template match="person">
I found a "person" element
<xsl:apply-templates select="firstName"/>
</xsl:template>
只有这样,模板#2才会运行 . 我理解正确吗?
3 回答
到目前为止同意这两个答案;您对模板#2不会被处理的评估是完全正确的 .
请注意,节点的子节点(即其子元素,注释,文本和处理指令,但不是属性)仅在两个方面有特殊之处:
select
属性的默认值是“node()
”,用于选择子项的XPath,以及根节点和元素节点的内置模板规则是处理子节点 .
除了这两个方面,孩子在选择要处理的节点时没有特殊的地位 . 您可以选择所需的任何节点,包括祖先 . 您可以按照自己喜欢的顺序遍历树 . 证明这一点的一种极端方法是编写一个反转文档层次结构的样式表(将其颠倒) . (您可能希望使用其他模式,以便在处理父节点时调用与处理子节点时不同的规则 . )
我还想检查并确保您了解"root node"(在XPath / XSLT 2.0中重命名为"document node")与根(或文档)元素之间的区别 . 在您的示例XML中,<person>不是根节点;它是最外层的元素,它本身是根节点的子节点,XPath / XSLT数据模型中每个树的根处都是不可见的外部容器 .
如果要控制bat的处理权限,可以始终使用<xsl:template match =“/”>或(假设源树表示格式良好的XML文档而不是片段)<xsl:template match = “/ *”> . 他们是替代方法 . 后者的一个特征是包含match =“/”规则的导入代码将在之前触发,因为显式模板规则(即使它们具有最低的导入优先级)始终优先于内置模板规则 . 如果您没有在导入样式表中明确地使用<xsl:template match =“/”>,那么,在导入包含它的代码之前,您依赖于根节点的内置模板规则(将模板应用于children - 在这种情况下,将模板应用于<person>元素子项 .
在这个例子中,另一种控制蝙蝠的方法是使用match =“/ person” . 这样的规则将匹配任何<person>元素,前提是它是根节点的子节点 . 如果XML没有<person>作为其最外层元素,那么它将不会被调用 . 如果你还有<xsl:template match =“/”,那么它将首先被调用;只有match =“/”规则明确将模板应用于子项时,才会调用match =“/ person”(或match =“/ *”) .
对,那是正确的 . 您必须显式调用apply-templates以在树中进一步遍历 . 您始终可以使用更通用的
<xsl:apply-templates />
(不带@select)将模板应用于每个子节点(除了该元素的属性,必须使用select = "@*"明确选择) .但是,您也可以使用
<xsl:copy-of select="person" />
,它将直接复制任何选定的元素及其所有子元素,依此类推 .是的,你是对的 . 您可能已经知道,这也取决于您如何“进入”apply-templates逻辑 . 在上面的示例中,如果您没有“person”的模板,则默认模板规则将被触发(对于调用apply-templates的点的所有子节点) .
但是,如果在样式表中定义了任何模板(与apply-templates调用中的任何子节点匹配),则从该节点开始将模板应用于子节点将由再次调用apply-templates的模板决定,否则它们将只是忽略 .