【问题标题】:xsl:key not working when looping through nodeset obtained with xalan:nodeset循环通过使用 xalan:nodeset 获得的节点集时,xsl:key 不起作用
【发布时间】:2013-08-06 09:28:33
【问题描述】:

我发现了一个 xsl:key 似乎不起作用的情况。
我将 XSLT 1 与 Xalan(已编译)一起使用,这就是正在发生的事情:

1.- 这工作:名为 test1 的密钥工作正常:

<xsl:variable name="promosRTF">
  <xsl:copy-of select="promo[@valid='true']"/>
</xsl:variable>
<xsl:variable name="promos" select="xalan:nodeset($promosRTF)" />

<!-- now the key: when defined and used here it works fine: -->
<xsl:key name="test1" match="//promo" use="'anytext'" />
<xsl:for-each select="key('test1','anytext')/*">
  loop through elements in key... ok, works fine
</xsl:for-each>

<xsl:for-each select="$promos/*">
  ..loop through elements in variable $promos ...it is not empty so the loop iterates several times
</xsl:for-each>

2.- 这不起作用:密钥 test1 现在已定义并使用(我猜这是重点)在一个循环中遍历使用 xalan:nodeset 获得的元素

<xsl:variable name="promosRTF">
  <xsl:copy-of select="promo[@valid='true']"/>
</xsl:variable>
<xsl:variable name="promos" select="xalan:nodeset($promosRTF)" />

<xsl:for-each select="$promos/*">
  <!-- now the key: when defined and used (or just used) inside this for-each loop it does nothing: -->
  <xsl:key name="test1" match="//promo" use="'anytext'" />
  <xsl:for-each select="key('test1','anytext')/*">
    loop through elements in key... NOTHING HERE, it does not work :(
  </xsl:for-each>

  ..loop through elements in variable $promos ...it is not empty so iterates several times
</xsl:for-each>

有人知道发生了什么吗?请注意,变量 $promos 不是空的,所以循环确实在迭代,它是其中使用的键,它什么都不做。

非常感谢您。

PS:在 Martin 的回答之后,我发布了这个替代代码,它也不起作用:

<xsl:variable name="promosRTF">
  <xsl:copy-of select="promo[@valid='true']"/>
</xsl:variable>
<xsl:variable name="promos" select="xalan:nodeset($promosRTF)" />

<!-- now the key: defined as a first level element: -->
<xsl:key name="test1" match="//promo" use="'anytext'" />
<xsl:for-each select="$promos/*">
  <!-- but used inside this for-each loop it does nothing: -->
  <xsl:for-each select="key('test1','anytext')/*">
    loop through elements in key... NOTHING HERE, it does not work :(
  </xsl:for-each>

  ..loop through elements in variable $promos ...it is not empty so iterates several times
</xsl:for-each>

解决方案:在 Martin 的 cmets 中是问题的关键:结果树片段中的节点被视为不同文档中的节点 .
Martin 也指出了解决方法:在 XSLT 1.0 中,您需要使用 for-each 更改上下文节点,然后在 for-each 中调用 key。 然后此代码将起作用:

<xsl:variable name="promosRTF">
  <xsl:copy-of select="promo[@valid='true']"/>
</xsl:variable>
<xsl:variable name="promos" select="xalan:nodeset($promosRTF)" />

<!-- now the key -->
<xsl:key name="test1" match="//promo" use="'anytext'" />
<xsl:for-each select="$promos/*">
  <!-- inside this for-each we are in a different *document*, so we must go back: -->
  <xsl:for-each select="/">
    <xsl:for-each select="key('test1','anytext')/*">
      loop through elements in key... and now IT WORKS, thanks Martin :)
    </xsl:for-each>
  </xsl:for-each>

  ..loop through elements in variable $promos ...it is not empty so iterates several times
</xsl:for-each>

【问题讨论】:

    标签: xslt xslt-1.0 xalan xslkey


    【解决方案1】:

    我很惊讶将xsl:key 放入for-each 中没有出现错误。在http://www.w3.org/TR/xslt#key 中,您可以看到xsl:key 被定义为&lt;!-- Category: top-level-element --&gt; 顶级元素,因此您需要将其作为xsl:stylesheetxsl:transform 的子元素。

    【讨论】:

    • 谢谢你指出这一点,马丁。我开始我的代码将密钥定义为 xsl:stylesheet 的子项,并尝试了几个选项以上面的 de 代码结束,它不会引发任何错误但什么也不做。如果我将键定义为第一级元素,但我通过 xalan:nodeset 生成的元素在循环内使用它,它也不会执行任何操作。
    • 代码中唯一的其他潜在问题是每个文档/树都构建了键,因此结果树片段(转换为节点集)中的节点被视为不同文档中的节点。在 XSLT 2.0 中,key 函数采用第三个参数来允许您传入要搜索的文档节点(或更一般地是子树的根)。在 XSLT 1.0 中,您需要使用 for-each 更改上下文节点,然后在 for-each 中调用 key。这意味着通常在 for-each 之外更改上下文节点,您首先需要将其他文档存储在变量中。
    • ...我在怀疑类似的事情。在接受你的回答之前我会做一些测试,马丁,非常感谢你。
    • 嗨,马丁,就是这样。如果我在 中调用 key,它会按预期工作。再次感谢。 (尽管解决方案在评论中,但我接受了答案)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-10-01
    • 2018-01-10
    • 2018-12-25
    • 2014-05-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多