Visitar URL original
Provide unordered collection diff support · Issue #111 · xmlunit/xmlunit · GitHub
Skip to content

Provide unordered collection diff support #111

Open

Description

@izeye

The current implementation of Diff looks to have an assumption that collection is ordered and doesn't look there's any switch to the assumption so that unordered collections can be handled.

It would be nice to provide unordered collection diff based on XML schema.

This is a test to illustrate what I'm trying to suggest: https://github.com/izeye/samples-java-branches/blob/master/src/test/java/learningtest/org/xmlunit/diff/DiffTests.java#L62-L82

Activity

  1. bodewig commented on Feb 27, 2018

    @bodewig
    Member

    XMLUnit is not aware of XML-Schema when it calculates differences, although this would be a great enhancement see also #88 .

    If element order is not significant for you, you can tell the difference engine by providing a DifferenceEvaluator. In your example

        .withDifferenceEvaluator(DifferenceEvaluators.chain(
            DifferenceEvaluators.Default,
            DifferenceEvaluators.downgradeDifferencesToSimilar(ComparisonType.CHILD_NODELIST_SEQUENCE)
        ))
    

    should work.

  2. izeye commented on Feb 28, 2018

    @izeye
    Author

    @bodewig Thanks for the quick feedback!

    Global switch for unordered collection will work for my immediate needs but the suggestion didn't work for me. It might be a fault on my end when applying your suggestion as I'm almost new to XMLUnit.

    This is what I tried with your suggestion: https://github.com/izeye/samples-java-branches/blob/master/src/test/java/learningtest/org/xmlunit/diff/DiffTests.java#L88-L105

  3. bodewig commented on Feb 28, 2018

    @bodewig
    Member

    Ah, in your case XMLUnit simply doesn't compare the elements you probably want it to compare.

    The person elements are siblings and you tell XMLUnit to match elements by their names and nested text. The person elements haven't got any nested text themselves, so XMLUnit picks them in order and you end up comparing the wrong persons - and thus see differences. I'd recommend using the Hamcrest matchers or include diff.toString() in your assertThat so that you can better see what kind of differences have been detected.

    In order to make your test pass you need to help XMLUnit matching the correct persons. It looks as if your person element was defined by the nested text of the id child element. In that case something like

    .withNodeMatcher(new DefaultNodeMatcher(conditionalBuilder()
        .whenElementIsNamed("person").thenUse(byXPath("./id", byNameAndText))
        .elseUse(byNameAndText)
        .build())

    should work, I haven't tried it. (just assume there was a static import on ElementSelectors so I can save typing :-))

    See https://github.com/xmlunit/user-guide/wiki/SelectingNodes for all the details.

  4. added a commit that references this issue on Feb 28, 2018
  5. izeye commented on Feb 28, 2018

    @izeye
    Author

    @bodewig Thanks again for the quick response!

    I think I understand your first advice now thanks to your second advice and I updated my tests based on it: https://github.com/izeye/samples-java-branches/blob/master/src/test/java/learningtest/org/xmlunit/diff/DiffTests.java#L89-L123

    Both work like a charm 👍

    I'm happy with the current solution for now but I'd like to keep this issue open for a possible enhancement based on XML schema for ordered and unordered mixed documents diff.

  6. bodewig commented on Feb 28, 2018

    @bodewig
    Member

    Glad it worked.

    Keeping the issue open as an enhancement request is fine with me, I've labeled it accordingly.

  7. michailangelo commented on Jul 2, 2019

    @michailangelo

    If the strings were like this :

    String xml1 = <persons><person><id>1</id><name><firstName>Johnny</firstName></name></person><person><id>2</id><name><firstName>John</firstName></name></person></persons>
    String xml2 = <persons><person><id>2</id><name><firstName>John</firstName></name></person><person><id>1</id><name><firstName>John</firstName></name></person></persons>

    How would you use multiple selectors to make the comparison?

  8. bodewig commented on Jul 2, 2019

    @bodewig
    Member

    @michailangelo I think this is a different question, so please open a new issue.

  9. michailangelo commented on Jul 2, 2019

    @michailangelo

    I thought this is relevant to the discussion before but I opened a new issue anyway :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions