язык xsl:ключ не работает, когда зацикливания через множество узлов, полученных с отключено:возможные


Я нашел случай, когда ключ xsl:, кажется, не работает.
Я использую XSLT 1 с Xalan (compiled), и вот что происходит:

1.- Это работает: ключ назван тест1 прекрасно работает:

<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 : после ответа Мартина я публикую этот альтернативный код, который тоже не работает:

<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>

Решение: в комментариях Мартина был ключ к проблеме: узлы во фрагменте результирующего дерева рассматриваются как узлы в другом документе.
Мартин указал обходной путь тоже: в XSLT 1.0 необходимо изменить узел контекста с помощью for-each, а затем вызвать ключ внутри for-each. тогда этот код будет работать:

<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>
1 4

1 ответ:

Я удивлен, что вы не получаете ошибку, помещая xsl:key в for-each. В http://www.w3.org/TR/xslt#key вы можете видеть, что xsl:key определяется как элемент верхнего уровня <!-- Category: top-level-element -->, поэтому вам нужно поместить его в качестве дочернего элемента xsl:stylesheet или xsl:transform.