Xsl: key does not work when passing through a set of nodes obtained using xalan: nodeset

I found a case where xsl: the key does not seem to work.
I am using XSLT 1 with Xalan (compiled), and this is what happens:

1.- It works: a key called test1 works fine:

<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.- This does not work: the test1 key is now defined and used (which, in my opinion, is an important point) inside a loop that iterates through the elements obtained using xalan: a set of nodes

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

Does anyone know what is going on? Note that the $ promos variable is not empty, so the loop does iterate, it is the key used inside it that does nothing.

Thank you in advance.

PS : after Martin’s response, I send this alternative code, which also doesn’t work:

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

Solution: Martin’s comments had a key to the problem: nodes in a fragment of the result tree are considered nodes in another document .
Martin pointed out a workaround: In XSLT 1.0, you need to change the context of the node, using for each and then a call key inside each of them. This code will work then:

 <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> 
+4
source share
1 answer

I am surprised that you did not receive the error by putting xsl:key in for-each . In http://www.w3.org/TR/xslt#key you can see that xsl:key is defined as a top level element <!-- Category: top-level-element --> , so you need to set it as child of xsl:stylesheet or xsl:transform .

+1
source

Source: https://habr.com/ru/post/1495491/


All Articles