遍历使用xalan:nodeset获得的节点集时,xsl:key不起作用

Fer*_*ndo 5 xslt xalan xslkey xslt-1.0

我发现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>
Run Code Online (Sandbox Code Playgroud)

2.-这不起作用:现在在循环遍历xalan:nodeset获得的元素的循环内定义并使用了密钥test1(我想这是重点)。

<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>
Run Code Online (Sandbox Code Playgroud)

有人知道发生了什么吗?请注意,变量$ 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>
Run Code Online (Sandbox Code Playgroud)

解决方案:在Martin的评论中,问题的关键在于:结果树片段中的节点被视为另一个文档中的节点
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>
Run Code Online (Sandbox Code Playgroud)

Mar*_*nen 2

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

  • 代码中唯一的其他潜在问题是键是按文档/树构建的,因此结果树片段中的节点(转换为节点集)被视为不同文档中的节点。在 XSLT 2.0 中,“key”函数采用第三个参数,允许您传入要搜索的文档节点(或更一般地说是子树的根)。在 XSLT 1.0 中,您需要使用“for-each”更改上下文节点,然后在“for-each”内调用“key”。这意味着通常在更改上下文节点的“for-each”之外,您首先需要将其他文档存储在变量中。 (3认同)