XSLT文档中的模板以什么顺序执行,它们是否与源XML或缓冲输出匹配?

Dea*_*ane 66 xslt

这是一直让我对XSLT感到困惑的事情:

  1. 模板的执行顺序是什么,以及
  2. 当它们执行时,它们是否匹配(a)原始源XML,或者(b)XSLT的当前输出到那一点?

例:

<person>
  <firstName>Deane</firstName>
  <lastName>Barker</lastName>
</person>
Run Code Online (Sandbox Code Playgroud)

这是XSLT的一个片段:

<!-- Template #1 -->
<xsl:template match="/">
  <xsl:value-of select="firstName"/> <xsl:value-of select="lastName"/>
</xsl:template>

<!-- Template #2 -->
<xsl:template match="/person/firstName">
  First Name: <xsl:value-of select="firstName"/>
</xsl:template>
Run Code Online (Sandbox Code Playgroud)

关于这个的两个问题:

  1. 我假设模板#1将首先执行.我不知道为什么我会这么想 - 是不是因为它首先出现在文件中?
  2. 模板#2会执行吗?它匹配源XML中的节点,但是当我们到达此模板时(假设它运行第二个),"firstName"节点将不在输出树中.

那么,"后来的"模板是否会受到"早期"模板中发生的事情的影响,或者它们是否对源文档进行操作,而忽略了"先前"转换为它们的内容?(所有这些单词都在引号中,因为当我真的不知道如何确定模板顺序时,我发现很难讨论基于时间的问题...)

在上面的例子中,我们有一个在根节点("/")上匹配的模板 - 当它完成执行时 - 基本上从输出中删除了所有节点.在这种情况下,这是否会抢占所有其他模板,因为在第一个模板完成后没有任何内容可以匹配?

到目前为止,我一直关注以后的模板没有执行,因为他们操作的节点没有出现在输出中,但反过来呢?"早期"模板是否可以创建"后期"模板可以执行某些操作的节点?

在与上面相同的XML上,考虑这个XSL:

<!-- Template #1 -->
<xsl:template match="/">
  <fullName>
    <xsl:value-of select="firstName"/> <xsl:value-of select="lastName"/>
  </fullName>
</xsl:template>

<!-- Template #2 -->
<xsl:template match="//fullName">
  Full Name: <xsl:value-of select="."/>
</xsl:template>
Run Code Online (Sandbox Code Playgroud)

模板#1创建一个名为"fullName"的新节点.模板#2在同一节点上匹配.模板#2会执行,因为当我们到达模板#2时,输出中存在"fullName"节点吗?

我意识到我对XSLT的"禅"一无所知.到目前为止,我的样式表包含一个匹配根节点的模板,然后从那里完全是程序性的.我厌倦了这样做.我宁愿真正理解XSLT,因此我的问题.

Eva*_*enz 83

我喜欢你的问题.你对你还不了解的内容非常清楚.你只需要把东西绑在一起.我的建议是你读过"XSLT如何工作",这是我写的一章,准确地解决了你所问的问题.我很想知道它是否能为你们联系起来.

不太正式,我会采取措施回答你的每一个问题.

  1. 模板的执行顺序是什么,以及
  2. 当它们执行时,它们是否匹配(a)原始源XML,或者(b)XSLT的当前输出到那一点?

在XSLT处理的任何给定点,在某种意义上,有两个上下文,您将其标识为(a)和(b):您在源树中的位置以及您在结果树中的位置.您在源树中的位置称为当前节点.当您选择要使用XPath处理的任意节点集时,它可以在源树周围进行更改和跳转.但是,从概念上讲,您永远不会以同样的方式"跳转"结果树.XSLT处理器以有序的方式构建它; 首先,它创建结果树的根节点; 然后它添加子项,按文档顺序构建结果(深度优先).[您的帖子激励我再次获取XSLT实验的软件可视化......]

样式表中模板规则的顺序永远不重要.您无法通过查看样式表来了解模板规则将以何种顺序实例化,实例化规则的次数,甚至是否完全实例化.(match="/"是一个例外;你总是可以知道它会被触发.)

我假设模板#1将首先执行.我不知道为什么我会这么想 - 是不是因为它首先出现在文件中?

不.即使你把它放在文档的最后,它也会被称为第一个.模板规则顺序永远不重要(除非在错误条件下,当您有多个具有相同优先级的模板规则匹配同一节点时;即使这样,它对于实现者来说是可选的,您永远不应该依赖这种行为).它首先被调用,因为每当你运行XSLT处理器时总会发生的第一件事是虚拟调用<xsl:apply-templates select="/"/> .一个虚拟调用构造整个结果树.它外面没有任何事情发生.您可以通过定义模板规则来自定义或"配置"该指令的行为.

模板#2会执行吗?它匹配源XML中的节点,但是当我们到达此模板时(假设它运行第二个),"firstName"节点将不在输出树中.

模板#2(也没有任何其他模板规则)永远不会被触发,除非您<xsl:apply-templates/>match="/"规则中的某个地方有呼叫.如果你没有,那么除了match="/"触发之外没有模板规则.可以这样考虑:要使模板规则被触发,它不能只匹配输入中的节点.它必须匹配您选择处理(使用<xsl:apply-templates/>)的节点.相反,它将继续匹配节点,因为您选择处理节点的次数.

[ match="/" 模板] 会抢先执行所有其他模板,因为在第一个模板完成后没有任何内容可以匹配吗?

该规则优先于包括<xsl:apply-templates/>在其中的其他地方.仍然有很多节点可以在源树中处理.他们总是在那里,适合采摘; 根据需要处理每一个.但使用模板规则处理它们的唯一方法是调用<xsl:apply-templates/>.

到目前为止,我一直关注以后的模板没有执行,因为他们操作的节点没有出现在输出中,但反过来呢?"早期"模板是否可以创建"后期"模板可以执行某些操作的节点?

并不是"早期"模板创建了一个要处理的新节点; 这是一个"早期"模板反过来使用相同的指令(<xsl:apply-templates)处理来自源树的更多节点.您可以将其视为递归调用相同的"函数",每次使用不同的参数(由上下文和select属性确定要处理的节点).

最后,你得到的是对同一个"function"(<xsl:apply-templates>)的递归调用的树形结构堆栈.而这个树结构与你的实际结果是同构的.不是每个人都意识到这一点,或者以这种方式思考过它; 那是因为我们还没有任何有效的可视化工具......

模板#1创建一个名为"fullName"的新节点.模板#2在同一节点上匹配.模板#2会执行,因为当我们到达模板#2时,输出中存在"fullName"节点吗?

不.进行处理链的唯一方法是以这种方式明确地设置它.创建一个变量,例如,$tempTree包含新<fullName>元素,然后像这样处理<xsl:apply-templates select="$tempTree">.要在XSLT 1.0中执行此操作,您需要使用扩展函数(例如exsl:node-set())包装变量引用,但在XSLT 2.0中它将按原样工作.

无论您是从原始源树还是在构造的临时树中处理节点,您都需要明确说明要处理的节点.

我们没有涉及的是XSLT如何获得其所有隐式行为.您还必须了解内置模板规则.我一直在编写样式表,甚至没有为根节点(match="/")包含明确的规则.相反,我依赖于根节点的内置规则(将模板应用于子节点),这与元素节点的内置规则相同.因此,我可以忽略输入的大部分,让XSLT处理器自动遍历它,只有当它遇到我感兴趣的节点时才会做一些特别的事情.或者我可以编写一个递归复制所有内容的规则(称为标识转换),仅在必要时覆盖它,以对输入进行增量更改.在您阅读"XSLT如何工作"之后,您的下一个任务是查找"身份转换".

我意识到我对XSLT的"禅"一无所知.到目前为止,我的样式表包含一个匹配根节点的模板,然后从那里完全是程序性的.我厌倦了这样做.我宁愿真正理解XSLT,因此我的问题.

我为你鼓掌 现在是时候采取"红色药丸":阅读"XSLT如何工作"

  • 来自@EvanLenz的精彩文章!! 非常感谢. (6认同)

mir*_*rod 6

模板始终与源XML匹配.因此,顺序并不重要,除非2个或更多模板匹配相同的节点.在这种情况下,有点违反直觉,触发了最后一个匹配模板的规则.

  • 我的理解是,如果2个或更多模板匹配相同的节点,那么将运行具有最特定匹配的模板.我假设你的意思是2或更多具有完全相同的匹配条件? (2认同)
  • sorta,规则在规范中给出:http://www.w3.org/TR/xslt#conflict.除非您使用优先级属性,否则许多模式最终都具有相同的优先级.请注意规范中该部分的最后一段:"XSLT处理器可能会发出错误信号". (2认同)