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)" /> <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/*"> <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)" /> <xsl:key name="test1" match="//promo" use="'anytext'" /> <xsl:for-each select="$promos/*"> <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)" /> <xsl:key name="test1" match="//promo" use="'anytext'" /> <xsl:for-each select="$promos/*"> <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>