xslt - "context"关于调用模板参数的含义

标签 xslt parameters xslt-2.0

我喜欢认为我对 XSLT 有很好的掌握,但以下内容让我难以理解:
为什么是 xsl:param无法从未显式声明的调用模板访问?换句话说,如果我从模板 A 调用模板 B:

样式表 1

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

   <xsl:template match="/" name="A"><!--This template is named "A" for convenience only.-->
      <xsl:param name="hello" select="hello "/>
      <xsl:param name="world" select="world!"/>
      <xsl:call-template name="B"/>
   </xsl:template>

   <xsl:template name="B">
      <xsl:value-of select="concat($hello,$world)"/>
   </xsl:template>

</xsl:stylesheet>

为什么模板 B 不自动采用模板 A 的参数作为上下文的一部分?我的理由如下。

显然,调用模板不会以任何方式影响上下文:

The selected <xsl:template> is evaluated with no change to the context: it uses the same context item, context position, and context size as the calling template1



现在,“上下文”在 XSLT 中的实际含义是什么,或者更准确地说,参数是否被视为上下文的一部分?构成上下文的事物包括2:
  • 所有变量声明( xsl:variablexsl:param )在计算表达式时的范围内,作为静态上下文的一部分
  • 范围内所有变量的值,作为动态上下文的一部分

  • 这使我相信以下样式表与我展示的第一个样式表相同:

    样式表 2
    <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    
       <xsl:template match="/" name="A">
          <xsl:param name="hello" select="hello "/>
          <xsl:param name="world" select="world!"/>
          <xsl:value-of select="concat($hello,$world)"/>
       </xsl:template>
    
    </xsl:stylesheet>
    

    但显然,只有第二个是正确的,而第一个会产生两个关于缺少变量声明的错误。如果模板调用不改变上下文并且参数被认为是上下文的一部分,为什么必须在被调用的模板中显式声明参数?

    为了清楚起见:
  • 我知道如何用 xsl:with-param 修改第一个样式表和参数声明——这不是我想要的。
  • 我知道 tunnel parameters在 XSLT 2.0 中 - 您不必解释它们或建议它们作为替代方案。我并不是在寻求一种在未声明参数的模板中使用参数的方法——我想知道为什么它们首先不可用。


  • 1 我的重点。请参阅 XSLT 2.0 程序员引用,Michael Kay,第 273 页。
    2 见规范的相关部分here或引用 Michael Kay 的 XSLT 2.0 Programmer's Reference,第 84f 页。

    最佳答案

    很好的问题,问得很好。

    您期望的行为在具有动态范围的语言中是自然的。但是 XSLT 对变量使用词法范围,而不是动态范围。

    您问现在,“上下文”在 XSLT 中的实际含义是什么,或者更准确地说,参数是否被视为上下文的一部分?

    简短的回答:是的,参数是静态上下文的一部分,用于其范围内的表达式(它的缺失是关于样式表中其他地方的表达式的静态上下文的事实);它的值是其范围内表达式的动态上下文的一部分。并且(至关重要)xsl:call-template指令确实会影响计算表达式的上下文。

    更长的答案:详情可在 the XSLT 2.0 spec 中找到.在 section 2.5规范告诉我们,上下文分为两部分:静态上下文和动态上下文。 Section 5.4提供完整的细节; section 5.4.1将“范围内变量”列为静态上下文的一个组成部分。

    section 9.7 中给出了变量的范围规则。 .关键是这样的:

    A local variable binding element is visible for all following siblings and their descendants, with two exceptions: it is not visible in any region where it is shadowed by another variable binding, and it is not visible within the subtree rooted at an xsl:fallback instruction that is a sibling of the variable binding element.



    您遇到的明显矛盾主要依赖于“调用模板不会影响上下文”的前提。这个前提实际上是不正确的,尽管事实上你拥有非常好的权威。

    section 10.1 ,规范说“xsl:call-template 指令不会改变焦点。”它并不是说指令不影响上下文。

    在您引用 Michael Kay 书中的段落中,我认为“上下文”一词可能最好是“上下文项”或“动态上下文”的缩写。即使在那个阅读句子上也不是很正确:因为 dynamic variables上下文的组成部分不同,被调用模板中的动态上下文与调用模板中的动态上下文并不完全相同。我认为您必须在此处减少 MK 的一些懈怠:所讨论的段落与他的书的 XSLT 1.0 版本基本没有变化,并且在 XSLT 1.0 中,在讨论上下文时,没有明确表示变量的动态绑定(bind)和名称的参数。但我认为可以公平地说,您在 MK 可能希望在下一次修订中更改的书中找到了一些内容。

    关于xslt - "context"关于调用模板参数的含义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22632983/

    相关文章:

    xml - 如何在 XSLT2 replace() 函数中转换 'mix and match' 实体?

    xslt - Biztalk 在 XSLT 转换方面呈爆炸式增长

    .net - 如何使用 XSLT 删除属性值与给定值不同的节点?

    c - 两个或多个命令行参数?

    dictionary - 从 dict 初始化不可变结构

    xml - 如何在我的转换输出中打印 '&#32' 的文字字符串

    xslt - 处理另一个 XSLT 样式表的输出

    Swift - 在没有参数的情况下调用 viewDidLoad 中的@IBAction 方法

    html - 从 XML 结构中的纯文本创建 HTML 列表