XMLUnit Compare Xml comparing wrong Nodes
Asked Answered
G

4

6

I am having an issue when you have the parent node in different order. For example:

Sample XML1

<level1>
   <name>FirstParent</name>
   <level2>
        <somefield>AAA</somefield>
   </level2>
   <level2>
        <somefield>BBB</somefield>
   </level2>       
</level1>
<level1>
   <name>SecondParent</name>
   <level2>
        <somefield>CCC</somefield>
   </level2>
   <level2>
        <somefield>DDD</somefield>
   </level2>
</level1>

Sample XML2

<level1>
   <name>SecondParent</name>
   <level2>
        <somefield>DDD</somefield>
   </level2>
   <level2>
        <somefield>CCC</somefield>
   </level2>
</level1>
<level1>
   <name>FirstParent</name>
   <level2>
        <somefield>BBB</somefield>
   </level2>
   <level2>
        <somefield>AAA</somefield>
   </level2>          
</level1>

When I debug the RecursiveElementNameAndTextQualifier, I see that it is getting FirstParent as controlnode and SecondParent as testnode. And, therefore, concluding correctly that the nodes are different. But what I need is to compare both FirstParent and both SeconParent with their correct match in the other file.

So, seems that I need to sort the higher level nodes first (?).

Does anybody know how can I overcome this? What should I check/modify/implement differently to pass the right tandem of parents to the ElementQualifier ?

Maybe, with the right directions, I can develop what is needed.

Glance answered 7/10, 2015 at 15:17 Comment(0)
O
2

You haven't specified whether you're using XMLUnit 1 or 2, but in version 2 (2.0.0-alpha-04) and using the DiffBuilder I was having this problem. The solution is to construct the Diff passing a non-default ElementSelector to Default Matcher:

import org.xmlunit.diff.Diff;
import org.xmlunit.builder.DiffBuilder;
import org.xmlunit.diff.ElementSelectors;
import org.xmlunit.diff.DefaultNodeMatcher;

. . .

Diff diff = DiffBuilder.
            compare(myExpectedResultXmlObj).
            withTest(myCompareToXmlObj).
            withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byName)). 
            build();

Assert.assertFalse(diff.toString(), diff.hasDifferences());

The key part being the withNodeMatcher line.

Officialdom answered 31/3, 2016 at 16:15 Comment(0)
T
1

You need to think about the conditions that are necessary to pick up the same branches of your document. From your description you want to compare the the two level1 elements with their order swapped. It sounds as if you wanted to identify the matching pairs by looking into the text content of the first name child element nested into it. And just on this text, nothing else.

This is not what RecursiveElementNameAndTextQualifier does. It compares the element names and nested texts of all child elements. And since the order of somefield elements is swapped, the nodes you'd like to compare are not eligible.

You see XMLUnit picking the level1 elements in order as it falls back to doing just that when no matching pairs of nodes have been found at all. If you set compareUnmatched to false you'd get CHILD_NODE_NOT_FOUND differences instead.

In XMLUnit 1.x (2.x hasn't been released, yet) you'll have to write an ElementQualifier that embeds the logic you need yourself, there is no built-in ElementQualifier that did exactly what you want.

Thilde answered 8/10, 2015 at 4:46 Comment(2)
Hey Stefan, thanks for the reply. Are you sure that is the ElementQualifier class the one I need to develop? Im not much of a Java guy but I can give it a try. Could you point me out what or when or where the selection of nodes for comparison begins? That way I can put the code to sort the elements before that and just send the right couple of nodes to compare to the existing functions. TYGlance
That may end up being a lot more complex. See the compareNodeList method in DifferenceEngine.Thilde
F
0

You'll need to provide your own ElementQualifier implementation. RecursiveElementNameAndTextQualifier will potentially match the same element from one document against multiple elements from the other.

Frangipane answered 7/10, 2015 at 15:32 Comment(2)
Inside the RecursiveElementNameAndTextQualifier I have the compareNodes call. That call is being passed FirstParent as currentControl and SecondParent as currentTest. Do you know when/where is that call being made?Glance
compareNodes() is called by the interface method qualifyForComparison(), which is called by the compare() method of Diff.Frangipane
W
0

For me, I also needed to add the method checkForSimilar() on the DiffBuilder.

Without it, the assert was in error saying that the sequence of the nodes was not the same (the position in the child list was not the same)

My code was :

Diff diff = DiffBuilder
    .compare(myExpectedResultXmlObj)
    .withTest(myCompareToXmlObj)
    .checkForSimilar()
    .withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byName))
    .build();
Wilmot answered 23/3, 2017 at 10:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.