首页 文章

除非apply-templates被明确调用,否则XSLT不会处理当前节点的子节点是否正确?

提问于
浏览
1

我想我知道答案,但我只想确认我正确理解这一点 .

当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 回答

  • 1

    到目前为止同意这两个答案;您对模板#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 =“/ *”) .

  • 2

    对,那是正确的 . 您必须显式调用apply-templates以在树中进一步遍历 . 您始终可以使用更通用的 <xsl:apply-templates /> (不带@select)将模板应用于每个子节点(除了该元素的属性,必须使用select = "@*"明确选择) .

    但是,您也可以使用 <xsl:copy-of select="person" /> ,它将直接复制任何选定的元素及其所有子元素,依此类推 .

  • 4

    是的,你是对的 . 您可能已经知道,这也取决于您如何“进入”apply-templates逻辑 . 在上面的示例中,如果您没有“person”的模板,则默认模板规则将被触发(对于调用apply-templates的点的所有子节点) .

    但是,如果在样式表中定义了任何模板(与apply-templates调用中的任何子节点匹配),则从该节点开始将模板应用于子节点将由再次调用apply-templates的模板决定,否则它们将只是忽略 .

相关问题