GNOME Bugzilla – Bug 530871
xsl:key, sibling axes
Last modified: 2013-12-13 17:06:18 UTC
Please describe the problem: This is a slighty modified version of a post to the Gnome XSLT library mailing list <XSLT@GNOME.org>. See: http://mail.gnome.org/archives/xslt/2008-April/msg00027.html The xsl:key does not seem to always work correctly in LibXSLT when its @use attribute involves any, or both, of the sibling axes. I happened to code something LibXSLT interprets differently than its fellow processors Saxon 6.5.5 and 9.0.0.2 (Java), Xalan-C 1.10.0 and Sablotron 1.0.3. All this occurs on Linux Ubuntu, both using the distribution package 1.1.20-0ubuntu2 (version 10120, according to xsltproc -V) and compiling from source (version 1.1.22, all tests passed, including key tests, using newest available LibXML2, version 2.6.31). $ /usr/local/bin/xsltproc -V Using libxml 20631, libxslt 10122 and libexslt 813 xsltproc was compiled against libxml 20631, libxslt 10122 and libexslt 813 libxslt 10122 was compiled against libxml 20631 libexslt 813 was compiled against libxml 20631 Steps to reproduce: The problem can be reproduced by using xsltproc to transform the supplied data using the supplied XSLT program. Here's my data. There are a number of ChGr elements identified by @ID and representing groups of TV channels. Some of those also have a @name. I call these super-groups and use them to refer to several related groups. What's related is implicitly defined by document order: The super-group a given ChGr belongs to is either its own @name or, in the case of its absence, the first preceding ChGr/@name in axis order. So we have (1,2,3), (4,5), (6,7,8), (9), (10,11) and (12). <ChannelGroups> <ChGr ID="1" name="Hauptsender"/><!-- super-group --> <ChGr ID="2"/><!-- part II of this super-group --> <ChGr ID="3"/><!-- part III --> <ChGr ID="4" name="Regionalsender"/><!-- new super-group --> <ChGr ID="5"/><!-- part II, and so on; super-group is: --> <ChGr ID="6" name="Lokalsender"/><!-- on self axis --> <ChGr ID="7"/><!-- on preceding-sibling axis --> <ChGr ID="8"/><!-- and so on --> <ChGr ID="9" name="Spartensender"/> <ChGr ID="10" name="Infosender"/> <ChGr ID="11"/> <ChGr ID="12" name="Sportsender"/> </ChannelGroups> For easy access, I define a key that returns the super-group ChGr element node for any given ChGr/@ID. <xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="text"/> <xsl:key name="super-group" match="ChGr[@name]" use=" @ID | following-sibling::ChGr[ not(@name) ][ preceding-sibling::ChGr[ @name ][ 1 ]/@ID = current()/@ID ]/@ID"/> <xsl:template match="ChannelGroups"> <xsl:value-of select="system-property('xsl:vendor')"/> <xsl:text> </xsl:text> <xsl:for-each select="ChGr"> <xsl:variable name="sg" select="key('super-group', @ID)/@ID"/> <xsl:value-of select="@ID"/> <xsl:text> </xsl:text> <xsl:value-of select="$sg"/> <xsl:if test="@ID = $sg"> *super*</xsl:if> <xsl:text> </xsl:text> </xsl:for-each> </xsl:template> </xsl:transform> Actual results: Here's the output. Saxon & Co LibXSLT ---------- ------- 1 1 *super* 1 1 *super* 2 1 2 3 1 3 4 4 *super* 4 4 *super* 5 4 5 6 6 *super* 6 6 *super* 7 6 7 8 6 8 9 9 *super* 9 9 *super* 10 10 *super* 10 10 *super* 11 10 11 12 12 *super* 12 12 *super* The key() lookups seem to fail where the super-group node is to be found on the preceding-sibling axis. I suspect this is a bug in LibXSLT. Is it? Expected results: I would expect the output of LibXSLT to be the same as the output of its fellow processors. Does this happen every time? The erroneous output happens every time. Other information:
Possibly a libxml2 XPath evaluation bug, but my head spins just looking at the example. Any way you could reduce the XSL and XML data to just expose the problem ? looking at xltproc -v output may help spot what is the actual problem, thanks, Daniel
Daniel, thanks for looking into this. You're right, the example is too confusing. (First bug report I've ever made.) Trying to reduce the complexity has actually exposed the bug. It does *not*, as claimed in the title I've given to this bug entry, pertain to the sibling axes. Instead, it has to do with the XSLT 1.0 current() function. I hope the following example will be clearer to you. $ cat libxslt-key-current.xml <Root> <Elm ID="1" name="a"/> <Elm ID="2"/> <Elm ID="3"/> <Elm ID="4" name="b"/> <Elm ID="5"/> <Elm ID="6" name="c"/> </Root> $ cat libxslt-key-current-simple.xsl <xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="text"/> <!-- a parameter to let you choose the key by name --> <xsl:param name="k" select="'k1'"/> <!-- A non-sensical key, to demonstrate the problem. --> <xsl:key name="k1" match="Elm[@name]" use=" @ID"/> <xsl:key name="k2" match="Elm[@name]" use="current()/@ID"/> <!-- And an equivalent key, which does not work. --> <xsl:template match="*"> <xsl:apply-templates select="*"/> </xsl:template> <xsl:template match="Elm"> <xsl:value-of select="@ID"/> <xsl:for-each select="key($k, @ID)/@name"> <xsl:text> </xsl:text><xsl:value-of select="."/> </xsl:for-each> <xsl:text> </xsl:text> </xsl:template> </xsl:transform> $ xsltproc libxslt-key-current-simple.xsl libxslt-key-current.xml 1 a 2 3 4 b 5 6 c $ xsltproc --stringparam k k2 libxslt-key-current-simple.xsl libxslt-key-current.xml 1 2 3 4 5 6 In both cases, the output should be as in the first case ("k1"). The spec says: "The current function returns a node-set that has the current node as its only member." -- http://www.w3.org/TR/xslt#function-current The spec does not say that during key creation, there is no current node. It says: "[...] a node x has a key with name y and value z if and only if there is an xsl:key element such that: [...] when the expression specified in the use attribute of the xsl:key element is evaluated with x as the current node and with a node list containing just x as the current node list [...]" -- http://www.w3.org/TR/xslt#element-key I hope this helps to clarify the issue. Thanks once more for taking care of this bug! Michael Ludwig
Fixed with commit ce5a0dd6: https://git.gnome.org/browse/libxslt/commit/?id=ce5a0dd6a70efdb214aba12fefc6bbf8c201b838
Danke … nach fünfeinhalb Jahren gefixt!!! :) I git-got your commit, compiled and tested, all good now! Thanks!