4

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.

Charles
  • 41
  • 2

4 Answers4

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.

Stefan Bodewig
  • 3,260
  • 15
  • 22
  • 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. TY – Charles Oct 08 '15 at 09:36
  • That may end up being a lot more complex. See the `compareNodeList` method in `DifferenceEngine`. – Stefan Bodewig Oct 08 '15 at 16:04
1

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.

Chris Peacock
  • 4,107
  • 3
  • 26
  • 24
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.

jsheeran
  • 2,912
  • 2
  • 17
  • 32
  • 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? – Charles Oct 07 '15 at 16:14
  • `compareNodes()` is called by the interface method `qualifyForComparison()`, which is called by the `compare()` method of `Diff`. – jsheeran Oct 07 '15 at 16:26
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();
Tom
  • 4,257
  • 6
  • 33
  • 49
pierre
  • 11
  • 1