I would like to be able to compare two nodes based on the values of their child nodes. Testing node equality with the =
operator just compares the string values of the respective nodes. I would like to compare them based on values in their child nodes.
To be a bit more specific, I would like <a>
and <b>
(below) to be equal, because the values of @id
are the same for <c>
elements that have matching @type
attributes also have matching @id
attributes.
<a>
<c type="type-one" id="5675"/>
<c type="type-two" id="3423"/>
<c type="type-three" id="9088"/>
</a>
<b>
<c type="type-one" id="5675"/>
<c type="type-two" id="3423"/>
</b>
But these would be different:
<a>
<c type="type-one" id="5675"/>
</a>
<b>
<c type="type-one" id="2342"/>
</b>
The only solution I can begin to see involves a laborious comparison with a for-each
statement, which I would like to avoid if possible.
If possible I would like to stick with XSLT 1.0. I am using xsltproc.
First of all, the relation called "equals" cannot have that name.
"Equals" means that the relation is an equivalence relation. By definition any equivalence relation
~
must be:Reflexive:
x ~ x
.Symmetric: if
x ~ y
theny ~ x
Transitive: if
x ~ y
andy ~ z
thenx ~ z
.Here is an example, showing that the proposed "equals" relation isn't transitive:
x
is:y
is:z
is:Now, we can see that
x ~ y
andy ~ z
. However, clearly this doesn't hold:x ~ z
This said, I am calling the relation "matches" and it is relaxed and not "equals".
Here is a solution to the problem, with the above adjustment:
Do note that this cannot be expressed with a single XPath expression, because XPath 1.0 (used within an XSLT 1.0 transformation) doesn't have range variables.
When this transformation is applied on the following XML document:
the wanted, correct result is produced:
When the same transformation is applied on this XML document:
again the correct result is produced:
Here is what I came up with. Given a toy data set like this:
This stylesheet shows how to test equality, as defined in the question.
This uses some extensions, which are available in xsltproc and other processors.