Compare XML ignoring element order
Asked Answered
E

2

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)
Evan answered 13/11, 2015 at 14:31 Comment(2)
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?Osmond
I replicated OP's problem, even when I added .checkForSimilar(). This seems contrary to the documentation at github.com/xmlunit/user-guide/wiki/… Adding the .withNodeMatcher() described below solved the problem.Quasijudicial
O
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))

Osmond answered 17/11, 2015 at 5:32 Comment(4)
Thank you, Stefan!Quasijudicial
@stefan...Will this work if nodes are at different places in the xml files?Pierson
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.Osmond
You may want to use a github issue for that.Osmond
B
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

Bobine answered 3/3, 2023 at 10:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.