Different xsl:key implementations (was Re: [xsl] Another key question)

Subject: Different xsl:key implementations (was Re: [xsl] Another key question)
From: "G. Ken Holman" <gkholman@xxxxxxxxxxxxxxxxxxxx>
Date: Thu, 17 Oct 2002 17:45:50 -0400
At 2002-10-17 11:38 -0700, Richard Lander wrote:
I'm trying to do something with keys and having a bit of trouble. In doing so, I've done some research with some sample data and come up with the following results.
...
<xslt:key name="sections" match="section" use="generate-id(current())"/>
...
I get the following result out of MSXML4.
...
<title>H1</title>
<para>IDAEAWY</para>
<para></para>

I note how the second paragraph is always empty ... no nodes are being extracted from the key table ... the question is why and I can think of two different reasons and can find processors supporting each reason.


What should happen?

My main question, is what does 'current()' mean in the context in which I've used it within xsl:key.

First read of section 12.2 of XSLT 1.0: --------------------------------------

According to the paragraph after the xsl:key prototype, the use= attribute is evaluated once for each node that matches the pattern ... it does *not* say that the current node list and current node are set to the matched node for the purposes of evaluating the use= expression.

During the processing of top-level constructs, the current node is the root node, therefore whenever you use current() in the use= expression, the root node will be returned.

Note that the test below demonstrates that both Saxon and MSXML uses the root node for current() during the evaluation of use=.

Second read of section 12.2 of XSLT 1.0:
---------------------------------------

The final sentence of the first paragraph after the xsl:key prototype introduces the bulleted list and the third bullet *does* say the current node list and the current node are set to the node being matched, which would indicate that current() returns the node being matched.

Section 12.4 states the current() function returns a node-set that has the current node as its only member, which must therefore (I would think) be the node being matched.

Note that the test below demonstrates that Xalan uses the matched node for the second of the two, but not the first which I assume is a bug, but definitely isn't returning the root node.

Conclusion
----------

I'm not an implementer, but I would have thought the same as you that because of the third bullet the current node and the current node list are set to the node being matched therefore the current() function should be returning the node being matched therefore the test below should be returning a count of two attributes for each access to the key table.

So, I would have thought Xalan was close to getting it right, though for some reason not on the first entry, which is wrong.

My gut feel is that both MSXML and Saxon are not returning the correct value for the execution of the current() function in the context of use=.

I look forward to hearing comments from the implementers.

..................... Ken


X:\samp>type key-current.xml <?xml version="1.0" encoding="iso-8859-1"?> <test att1='1' att2='2' att3='3'> <x this='a' that='b'>First X</x> <x this='c' that='d'>Second X</x> </test> X:\samp>type key-current.xsl <?xml version="1.0" encoding="iso-8859-1"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"; version="1.0">

<xsl:key name="atts-." match="x" use="count(./@*)"/>
<xsl:key name="atts-current" match="x" use="count(current()/@*)"/>
<xsl:key name="atts-root" match="x" use="count(current()/*/@*)"/>

<xsl:template match="/">
  <xsl:for-each select="key( 'atts-.', '0' )">
    Found 0 attributes in use= expression using "./@*"
  </xsl:for-each>
  <xsl:for-each select="key( 'atts-.', '1' )">
    Found 1 attribute in use= expression using "./@*"
  </xsl:for-each>
  <xsl:for-each select="key( 'atts-.', '2' )">
    Found 2 attributes in use= expression using "./@*"
  </xsl:for-each>
  <xsl:for-each select="key( 'atts-.', '3' )">
    Found 3 attributes in use= expression using "./@*"
  </xsl:for-each>
  <xsl:for-each select="key( 'atts-current', '0' )">
    Found 0 attributes in use= expression using "current()/@*"
  </xsl:for-each>
  <xsl:for-each select="key( 'atts-current', '1' )">
    Found 1 attribute in use= expression using "current()/@*"
  </xsl:for-each>
  <xsl:for-each select="key( 'atts-current', '2' )">
    Found 2 attributes in use= expression using "current()/@*"
  </xsl:for-each>
  <xsl:for-each select="key( 'atts-current', '3' )">
    Found 3 attributes in use= expression using "current()/@*"
  </xsl:for-each>
  <xsl:for-each select="key( 'atts-root', '0' )">
    Found 0 attributes in use= expression using "current()/*/@*"
  </xsl:for-each>
  <xsl:for-each select="key( 'atts-root', '1' )">
    Found 1 attribute in use= expression using "current()/*/@*"
  </xsl:for-each>
  <xsl:for-each select="key( 'atts-root', '2' )">
    Found 2 attributes in use= expression using "current()/*/@*"
  </xsl:for-each>
  <xsl:for-each select="key( 'atts-root', '3' )">
    Found 3 attributes in use= expression using "current()/*/@*"
  </xsl:for-each>
</xsl:template>

</xsl:stylesheet>

X:\samp>call ..\prog\xsltjavasaxon key-current.xml key-current.xsl saxon.out
Invoking Saxon jar....

X:\samp>call ..\prog\xsltjavaxalan key-current.xml key-current.xsl xalan.out
Invoking Xalan/Xerces jar: "key-current.xml" with "key-current.xsl" to "xalan.out"


X:\samp>call ..\prog\msxml key-current.xml key-current.xsl msxml.out
Invoking MSXML....

X:\samp>type saxon.out
<?xml version="1.0" encoding="utf-8"?>
    Found 2 attributes in use= expression using "./@*"

Found 2 attributes in use= expression using "./@*"

Found 0 attributes in use= expression using "current()/@*"

Found 0 attributes in use= expression using "current()/@*"

Found 3 attributes in use= expression using "current()/*/@*"

Found 3 attributes in use= expression using "current()/*/@*"

X:\samp>type xalan.out
<?xml version="1.0" encoding="UTF-8"?>

Found 2 attributes in use= expression using "./@*"

Found 2 attributes in use= expression using "./@*"

Found 0 attributes in use= expression using "current()/@*"

Found 2 attributes in use= expression using "current()/@*"

Found 0 attributes in use= expression using "current()/*/@*"

Found 0 attributes in use= expression using "current()/*/@*"

X:\samp>type msxml.out
<?xml version="1.0" encoding="UTF-16"?>
    Found 2 attributes in use= expression using "./@*"

Found 2 attributes in use= expression using "./@*"

Found 0 attributes in use= expression using "current()/@*"

Found 0 attributes in use= expression using "current()/@*"

Found 3 attributes in use= expression using "current()/*/@*"

Found 3 attributes in use= expression using "current()/*/@*"

X:\samp>rem Done!


-- G. Ken Holman mailto:gkholman@xxxxxxxxxxxxxxxxxxxx Crane Softwrights Ltd. http://www.CraneSoftwrights.com/s/ Box 266, Kars, Ontario CANADA K0A-2E0 +1(613)489-0999 (F:-0995) ISBN 0-13-065196-6 Definitive XSLT and XPath ISBN 0-13-140374-5 Definitive XSL-FO ISBN 1-894049-08-X Practical Transformation Using XSLT and XPath ISBN 1-894049-10-1 Practical Formatting Using XSL-FO Next public training: 2002-12-08,2003-02-03,06,03-03,06


XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list



Current Thread