10

With XMLUnit 2 how do you compare two documents without taking the element order into account?

I got this question for XMLUnit 1, but apparently the new API in v2 doesn't have the mentioned method anymore.

This is my current code:

Diff diff = DiffBuilder.compare(expected)
            .withTest(actual)
            .ignoreComments()
            .ignoreWhitespace()
            .checkForSimilar()
            .build();

assertFalse(diff.hasDifferences());

Edit to Stefan Bodewigs comment:

These are the two strings i compare with above snippet:

String expected = "<root><foo>FOO</foo><bar>BAR</bar></root>";
String actual = "<root><bar>BAR</bar><foo>FOO</foo></root>";

The reported diffs

Expected element tag name 'foo' but was 'bar' - comparing <foo...> at /root[1]/foo[1] to <bar...> at /root[1]/bar[1] (DIFFERENT)
Expected text value 'FOO' but was 'BAR' - comparing <foo ...>FOO</foo> at /root[1]/foo[1]/text()[1] to <bar ...>BAR</bar> at /root[1]/bar[1]/text()[1] (DIFFERENT)
Expected element tag name 'bar' but was 'foo' - comparing <bar...> at /root[1]/bar[1] to <foo...> at /root[1]/foo[1] (DIFFERENT)
Expected text value 'BAR' but was 'FOO' - comparing <bar ...>BAR</bar> at /root[1]/bar[1]/text()[1] to <foo ...>FOO</foo> at /root[1]/foo[1]/text()[1] (DIFFERENT)
Community
  • 1
  • 1
Imperative
  • 3,138
  • 2
  • 25
  • 40
  • The new API should ignore element order by default (this is what `DifferenceEvaluators.DEFAULT` does). Are you sure this is the difference you see and not anything else? – Stefan Bodewig Nov 13 '15 at 17:04
  • I replicated OP's problem, even when I added .checkForSimilar(). This seems contrary to the documentation at https://github.com/xmlunit/user-guide/wiki/DifferenceEvaluator#default-differenceevaluator Adding the .withNodeMatcher() described below solved the problem. – Charles Roth Apr 11 '16 at 20:54

2 Answers2

14

One difference that may need to become clearer in the 2.x documentation is the default ElementSelector - roughly what used to be ElementQualifier in 1.x. Where 1.x defaults to match elements by name, 2.x defaults to match elements in order. Maybe this is a bad idea.

Your Diff should work if you switch to matching on element names.

.withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byName))

Stefan Bodewig
  • 3,260
  • 15
  • 22
  • Thank you, Stefan! – Charles Roth Apr 11 '16 at 20:55
  • @stefan...Will this work if nodes are at different places in the xml files? – Abhijit Bashetti Sep 18 '19 at 05:23
  • depends on what different means. It works for siblings of the same parent element. Otherwise you need to ensure the "correct parent" elements are being compared to each other before even thinking about the elements themselves. XMLUnit starts at the root of the document tree and picks branches to compare, once a branch has been selected to be "the match" XMLUnit will not look into the other branches at all. – Stefan Bodewig Sep 19 '19 at 07:10
  • You may want to use a github issue for that. – Stefan Bodewig Sep 20 '19 at 14:31
0

You might need to add something along the lines of

.withDifferenceEvaluator(((comparison, outcome) -> {
    if (outcome == ComparisonResult.DIFFERENT && 
        comparison.getType() == ComparisonType.CHILD_NODELIST_SEQUENCE) {
           return ComparisonResult.EQUAL;
    }
return outcome;
})).build();

to your Diff builder

for me the solution mentioned above will not work as compareNodeLists has this hardcoded in DOMDifferenceEngine.compareNodes()

new Comparison(ComparisonType.CHILD_NODELIST_SEQUENCE...

i have raised a new ticket for this though bear in mind it could just be my lack of understading :-)

https://github.com/xmlunit/xmlunit/issues/258

ferng001
  • 46
  • 6