[xslt] xsl:key bug in libxslt 1.0.31



Firstly, apologies but I haven't been able to test this with libxslt 
1.0.32 as I'm on Windows. However, I couldn't see anything relevant in the 
ChangeLog.

If there are multiple <xsl:key> elements with the same name attribute 
value, only nodes matched by the first appear to be found when key() is 
used.

The following stylesheet contains its own test data.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
    xmlns:test="http://www.example.org/test";>
  <xsl:output method="xml" encoding="UTF-8" indent="yes"/>

  <xsl:key name="k" match="test:a" use="@a"/>
  <xsl:key name="k" match="test:b" use="@b"/>

  <xsl:template match="/">
    <test:data>
      <xsl:for-each select="key('k','1')">
        <xsl:copy-of select="."/>
      </xsl:for-each>
    </test:data>
  </xsl:template>

  <xsl:template match="text()|@*"/>

  <test:data>
    <test:a a="1"/>
    <test:b b="1"/>
  </test:data>
</xsl:stylesheet>

xsltproc keytest.xslt keytest.xslt yields:

<?xml version="1.0" encoding="UTF-8"?>
<test:data xmlns:test="http://www.example.org/test";>
  <test:a a="1"/>
</test:data>

The result _should_ be:

<?xml version="1.0" encoding="UTF-8"?>
<test:data xmlns:test="http://www.example.org/test";>
  <test:a a="1"/>
  <test:b b="1"/>
</test:data>

The output from the xsltproc -v flag is:

Added namespace: xsl mapped to http://www.w3.org/1999/XSL/Transform
Added namespace: test mapped to http://www.example.org/test
xsltPrecomputeStylesheet: removing ignorable blank node
xsltParseStylesheetProcess : found stylesheet
xsltParseStylesheetKey: name k
Add key k, match test:a, use @a
   resulting pattern //test:a
xsltParseStylesheetKey: name k
Add key k, match test:b, use @b
   resulting pattern //test:b
template has 1 inherited namespaces
xsltCompilePattern : parsing '/'
xsltCompilePattern : parsed /, default priority 0.500000
added pattern : '/' priority 0.500000
template has 1 inherited namespaces
xsltCompilePattern : parsing 'text()'
xsltCompilePattern : parsed text(), default priority -0.500000
xsltCompilePattern : parsing '@*'
xsltCompilePattern : parsed @*, default priority -0.500000
added pattern : 'text()' priority -0.500000
added pattern : '@*' priority -0.500000
xsltParseStylesheetTop : found foreign element data
parsed 2 templates
Resolving attribute sets references
Initializing keys on keytest.xslt
xsltInitCtxtKey: test:b evaluates to 1 nodes
xsl:key : node associated to(k,1)
xsltInitCtxtKey: test:a evaluates to 1 nodes
xsl:key : node associated to(k,1)
Registered 0 modules
Registering global variables
Registering global variables from keytest.xslt
xsltProcessOneNode: applying template '/' for /
xsltApplyOneTemplate: copy node data
xsltForEach: select key('k','1')
Get key k, value 1
xsltForEach: select evaluates to 1 nodes
xsltCopyOf: select .
xsltCopyOf: result is a node set

Reversing the order of xsl:key elements yields:

<?xml version="1.0" encoding="UTF-8"?>
<test:data xmlns:test="http://www.example.org/test";>
  <test:b b="1"/>
</test:data>

Static examination of keys.c (from 1.0.32) suggests that xsltAddKey 
generates a new xsltKeyDef for each xsl:key, and xsltInitCtxtKey generates 
a new xsltKeyTable for each xsltKeyDef, but that xsltGetKey only uses the 
_first_ matching xsltKeyTable to generate its result xmlNodeSet.

Regards,

Ian.




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]