[xslt] key() in match pattern of xsl:key



Should it be possible to reference a key in the match pattern of another? I did not find this topic addressed in the XSLT 1.0 recommendation or elsewhere on the web. Did I miss it?

libxslt's treatment of this case seems odd. I've tested with 1.1.15. For an example, please find the XML and XSLT documents at the end of this message. Inside the match pattern of key `keyAnotB', the key `keyB' is referenced. If `keyAnotB' is declared before `keyB', then the key() invocation for `keyB' returns the expected set of nodes. Otherwise, it returns the empty set.

Reading xsltproc -v, I see that key hashes are built in the reverse order of the declarations. That explains this behavior. However, the opposite build order seems more intuitive. What's correct?

I expected this output, and I get it when `keyAnotB' comes before `keyB':

   <?xml version="1.0"?>
   $A:
     1.0: A=1, B=1, AnotB=0
     2.0: A=1, B=0, AnotB=1
     3.0: A=1, B=0, AnotB=1
   $B:
     1.0: A=1, B=1, AnotB=0
     4.0: A=0, B=1, AnotB=0
     5.0: A=0, B=1, AnotB=0
   $AnotB:
     2.0: A=1, B=0, AnotB=1
     3.0: A=1, B=0, AnotB=1

When `keyAnotB' comes after `keyB', I get this instead:

   <?xml version="1.0"?>
   $A:
     1.0: A=1, B=1, AnotB=1
     2.0: A=1, B=0, AnotB=1
     3.0: A=1, B=0, AnotB=1
   $B:
     1.0: A=1, B=1, AnotB=1
     4.0: A=0, B=1, AnotB=0
     5.0: A=0, B=1, AnotB=0
   $AnotB:
     2.0: A=1, B=0, AnotB=1
     3.0: A=1, B=0, AnotB=1

Thanks.

Joel

---------------------------------------------------------
<?xml version="1.0" encoding="iso-8859-1"?>

<test>
  <A>1.0</A>
  <A>2.0</A>
  <A>3.0</A>
  <B>1.0</B>
  <B>4.0</B>
  <B>5.0</B>
</test>
---------------------------------------------------------
<?xml version="1.0" encoding="iso-8859-1"?>

<xsl:transform
  version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform";


<xsl:key name="keyA" match="A" use="." /> <xsl:key name="keyB" match="B" use="." /> <xsl:key name="keyAnotB" match="A[ not( key( 'keyB', . ) ) ]" use = "." /> <xsl:variable name="AnotB" select="//A[ not( key( 'keyB', . ) ) ]" />

<xsl:template match="/">

  <xsl:text>$A:&#10;</xsl:text>
  <xsl:for-each select="//A">
    <xsl:text>  </xsl:text><xsl:value-of select="." />
    <xsl:text>: A=</xsl:text>
    <xsl:value-of select="count( key( 'keyA', . ) )" />
    <xsl:text>, B=</xsl:text>
    <xsl:value-of select="count( key( 'keyB', . ) )" />
    <xsl:text>, AnotB=</xsl:text>
    <xsl:value-of select="count( key( 'keyAnotB', . ) )" />
    <xsl:text>&#10;</xsl:text>
  </xsl:for-each>

  <xsl:text>$B:&#10;</xsl:text>
  <xsl:for-each select="//B">
    <xsl:text>  </xsl:text><xsl:value-of select="." />
    <xsl:text>: A=</xsl:text>
    <xsl:value-of select="count( key( 'keyA', . ) )" />
    <xsl:text>, B=</xsl:text>
    <xsl:value-of select="count( key( 'keyB', . ) )" />
    <xsl:text>, AnotB=</xsl:text>
    <xsl:value-of select="count( key( 'keyAnotB', . ) )" />
    <xsl:text>&#10;</xsl:text>
  </xsl:for-each>

  <xsl:text>$AnotB:&#10;</xsl:text>
  <xsl:for-each select="$AnotB">
    <xsl:text>  </xsl:text><xsl:value-of select="." />
    <xsl:text>: A=</xsl:text>
    <xsl:value-of select="count( key( 'keyA', . ) )" />
    <xsl:text>, B=</xsl:text>
    <xsl:value-of select="count( key( 'keyB', . ) )" />
    <xsl:text>, AnotB=</xsl:text>
    <xsl:value-of select="count( key( 'keyAnotB', . ) )" />
    <xsl:text>&#10;</xsl:text>
  </xsl:for-each>

</xsl:template>

</xsl:transform>
---------------------------------------------------------


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