I have following xml. Note that node n1 and n3 have same children (order can be different). How can I write an XSL transformation to identify such nodes?
<Document>
<Node name="n1">
<Item value="v1">
<Item value="v2">
<Item value="v3">
</Node>
<Node name="n2">
<Item value="p1">
<Item value="p2">
<Item value="p3">
</Node>
<Node name="n3">
<Item value="v3">
<Item value="v1">
<Item value="v2">
</Node>
</Document>
This is my (HUMBLE) XSLT 1.0 approach. It's not as much elegant as others, and it might be a failure in many cases, but, according to the question, it does the job and it has also a certain degree of customization.
The check among the nodes is performed against a pattern built using a named template:
build-pattern
. For example, in your case I compare against a pattern built using all thevalue
attributes of a node; that is, the first node is compared against a pattern likev1v2v3
. The pattern is built upon elements with nameItem
. Obviously this pattern can be changed according to the requirements.When applied on this input:
Produces:
I've generalized the above transform to find nodes with same children:
One would need only to replace the named template
build-pattern
with the following two:For example, when the new transform is applied to the following document:
Produces:
Here is a complete XSLT 1.0 solution that is general enough so that it would produce correct results even when a
Node
is allowed to have children with any name:when applied on this XML document:
the wanted, correct result is produced:
Explanation:
This is a two-pass transformation.
The result of the first pass is an XML fragment containing
Node
elements with theirname
attribute and one newly added attribute:signature
. This is the concatenation of the names and values of all children (in normal, sorted form). The result of pass1 in this concrete case is the following:In pass 2 we use the Muenchian method for grouping all
Node
elements by theirsignature
attribute. The firstNode
in every group is represented in the output with a new attributematches
whose value is the space-delimited concatenation of thename
attributes of the remainingNode
elements in the current group.[edit]The XSLT 2.0 stylesheet
when applied to
outputs
If all the child Items have to match, then I think Martin's solution needs to be modified to use
It's possible this doesn't meet the requirement exactly, for example it will match a Node with values v1,v2,v2 if there is another node with values v1,v2,v3. But since the requirement wasn't specified very precisely, I've had to guess a little.
(Note Martin's solution is XSLT 1.0, whereas mine is XSLT 2.0. I'm not going to the effort of writing XSLT 1.0 code unless people explicitly say that's what they need.)
Here is an attempt to do it with XSLT 1.0:
When running the stylesheet with Saxon 6.5.5 against the sample input
I get the following result: