So I’m having trouble understanding why one XPath expression gets the nodes I want, while the other doesn’t.
First, the xml:
<doc>
<source id="225" clientID="567" matterID="225" level="2" />
<source id="226" clientID="993" matterID="226" level="2" />
<dest id="185" level="7" />
<dest id="226" level="7" />
</doc>
The keys in my xsl template are defined as follows:
<xsl:key name="sourceId" match="//source" use="@id" />
<xsl:key name="destId" match="//dest" use="@id" />
<xsl:key name="destLevel" match="//dest" use="@level" />
What I’m looking for are the source nodes, that match dest nodes on id, but have a different level attribute. The apply template that I figured would work in my head is the following:
<xsl:apply-templates select="source[key('destId', @id) and not(key('destLevel', @level))]" mode="update" />
But that doesn’t seem to work. A colleague suggested putting a not around an expression that matches the nodes I don’t want, and after a lot of trial and error, I thought this might work, to no effect:
<xsl:apply-templates select="source[not(not(key('destId', @id)) or not(key('destLevel', @level)))]" mode="update" />
Can anyone please walk me through what I need in order to solve this?
Edit: I previously thought I’d solved this with the second query, but it seems I was mistaken.
====Solution====
Dimitre Novatchev has a detailed breakdown of different ways to solve this, but my ultimate solution was actually slightly different than his.
In essence, I created a virtual key with the concat() function that combined the two attributes. That way, I could find nodes that matched the id, but not the id-level combo.
Extra key:
<xsl:key name="destByIdAndLevel" match="//dest" use="concat(@id,'+',@level)" />
Changed apply-template call:
<xsl:apply-templates select="source[key('destId', @id) and not(key('destByIdAndLevel',concat(@id,'+',@level)))]" mode="update" />
I. This transformation:
when applied on this XML document (an additional
sourceelement added to the provided XML document — to verify more cases):produces the wanted, correct result:
II. Solution using one key:
When this transformation is applied on the same XML document (above), again the same wanted, correct result is produced:
III. Solution with two keys:
This again produces the wanted, correct result: