GNOME Bugzilla – Bug 607893
Problem with <xsl:key />
Last modified: 2013-12-13 21:11:39 UTC
I'm trying to cross-reference elements and found a problem. Here's the very short XML data: <test> <h level="1" /> <!-- id1 --> <h level="2" /> <!-- id2 --> <h level="2" /> <!-- id3 --> <h level="1" /> <!-- id4 --> <h level="2" /> <!-- id5 --> </test> For each <h />, I want to calculate the <h />'s that follow and have a level higher than the current one. The search should stop with the next following <h /> which has a higher level. This is the expression to be evaluated on each <h /> node: (preceding::h[ @level < current()/@level ])[last()] Let's do it manually first (I identify each node by it's id: so id3 is the third node in the above document, i.e. <h level="2" />) +------+--------------+ | Node | node-set | +------+--------------+ | id1 | {} | +------+--------------+ | id2 | {id1} | +------+--------------+ | id3 | {id1} | +------+--------------+ | id4 | {} | +------+--------------+ | id5 | {id4} | +------+--------------+ This is my stylesheet: <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/> <xsl:key name="F" match="h" use=" generate-id( (preceding::h[ @level < current()/@level ]) [last()] )"/> <!-- start --> <xsl:template match="/*"> <dump> <xsl:for-each select="//h" > <xsl:variable name="hid" select="generate-id(.)" /> <xsl:value-of select=" concat($hid,' : {')" /> <xsl:for-each select=" key('F',$hid) " > <xsl:value-of select="concat(' ',generate-id(.))" /> </xsl:for-each> <xsl:value-of select=" '} ' " /> </xsl:for-each> </dump> </xsl:template> </xsl:stylesheet> Here is the output when using Saxon-HE (9.x): <dump> d1e5 : { d1e11 d1e16} d1e11 : {} d1e16 : {} d1e20 : { d1e24} d1e24 : {} </dump> That's correct according to table calculated manually above. Next, xsltproc --version: Using libxml 20706, libxslt 10126 and libexslt 815 xsltproc was compiled against libxml 20706, libxslt 10126 and libexslt 815 libxslt 10126 was compiled against libxml 20706 libexslt 815 was compiled against libxml 20706 Then the output: <dump> id70347 : {} id70357 : {} id70365 : {} id70374 : {} id70383 : {} </dump> Eh, sorry, *not* correct. I have no clue what went on. I am suspiciuous though, that it has something to do with function current(). According to my understanding, current() should change the meaning. Usually, current() and '.' are the same. When using in predicate above, current() should indeed become the node on which the expr is being evaluated. On the other hand, if you simply calculate the above expr outside of <xsl:key />, as here shown <xsl:for-each select="//h" > <xsl:value-of select=" preceding::h[@level < current()/@level] " /> </xsl:for-each> then everything - especially current() - works fine.
Fixed with commit ce5a0dd6: https://git.gnome.org/browse/libxslt/commit/?id=ce5a0dd6a70efdb214aba12fefc6bbf8c201b838
I'm glad to notice that this bug got fixed, especially since the popularity of this problem was rather low :-)