Search

hi,

i have noticed that i get inconsistent results when using xsl:key to compare two node-sets against each other. i have the following setup:

<xsl:variable name="A">
    <key>a</key>
    <key>c</key>
</xsl:variable>

<xsl:variable name="B">
    <item>a</item>
    <item>b</item>
    <item>c</item>
</xsl:variable>

<xsl:key name="compare" match="key" use="exsl:node-set($A)/key"/>

<xsl:variable name="result">
     <xsl:for-each select="exsl:node-set($B)/item[not(key('compare', .))]">
        <item><xsl:value-of select="." /></item>
    </xsl:for-each>
</xsl:variable>

now, $result should hold one item (b) and it will most of the time, but sometimes it will just have all 3 original nodes in there. this happens very randomly. i have never experienced this behavior before.

has no one ever had this problem before? i never had problems with xsl:key before but this was all on a java based processor (i believe it was XALAN) is this maybe a bug with libXML? this is really frustrating me :(

also, maybe i am thinking to complicated here and the result can be achieved in simpler steps.

any help would be appreciated.

thanks
daniel

has no one ever had this problem before?

Nope, sorry.

also, maybe i am thinking to complicated here and the result can be achieved in simpler steps.

This should do it :)

<xsl:variable name="a-ns">
   <key>a</key>
   <key>c</key>
</xsl:variable>

<xsl:variable name="b-ns">
   <item>a</item>
   <item>b</item>
   <item>c</item>
</xsl:variable>

<xsl:variable name="a" select="exsl:node-set($a-ns)"/>
<xsl:variable name="b" select="exsl:node-set($b-ns)"/>

<xsl:copy-of select="$b/item[ . != $a/key ]"/>

If above doesn't work, try this one:

<xsl:copy-of select="$b/item[ text() != $a/key/text() ]"/>

You should need keys if you're doing fancy stuff like Muenchian grouping. Otherwise, simple xPath cross-match like that should suffice.

hi vlad,

thanks for the info! :)

i thought i had to use a recursive template or multiple for-each blocks to compare two node-sets but it seems that is only true for result-tree-fragments. is this so?

sadly your code does not work for me. it returns abc. strangely if i do the opposite and use <xsl:copy-of select="$b/item[ . = $a/key ]"/> it returns ac so the compare seems to basically work.

Try this one:

<xsl:copy-of select="$b/item[ not(. = $a/key) ]"/>

i thought i had to use a recursive template or multiple for-each blocks to compare two node-sets but it seems that is only true for result-tree-fragments. is this so?

Woot? :) If you need to get the difference between 2 node sets, no matter their source, just use xpath.

If you need to compare node sets deeper than one level, then you have to apply some sort of recursive templates, but the basic comparison is done by this xPath as well.

May I ask what's the context of this comparison? Perhaps it is not needed or something else.

thx, that works :)

concerning the comparability of node-sets i always thought that the processor would simply run through all nodes and only compare the last ones against each other.

because if you do:

<xsl:choose>
  <xsl:when test="$a/key = $b/item">identical</xsl:when>
  <xsl:otherwise>not identical</xsl:otherwise>
</xsl:choose>

the two node-sets will turn out to be "identical".

but as it turns out the processor really compares all nodes but it is simply defined that it shall return true if one node from the first set can be found in the second one. now, that seems like a really long stretch to me :D

well, learnt something today! thanks again! :)

Create an account or sign in to comment.

Symphony • Open Source XSLT CMS

Server Requirements

  • PHP 5.3-5.6 or 7.0-7.3
  • PHP's LibXML module, with the XSLT extension enabled (--with-xsl)
  • MySQL 5.5 or above
  • An Apache or Litespeed webserver
  • Apache's mod_rewrite module or equivalent

Compatible Hosts

Sign in

Login details