Search code examples
javaxmlxmlunit

XMLUnit - Added Tags?


When comparing the following two documents with XMLUnit (latest version- 2.3.0) In this document, the order of elements is irrelevant, however XMLUnit is taking this into account, and since the new element is appended to the beginning of the parent tag, it is detecting multiple changes when only one has occured.

Original XML (previous):

<ACVS>
    <ACV>
        <N>735</N>
        <C>S135</C>
    </ACV>
    <ACV>
        <N>736</N>
        <C>C0S135</C>
    </ACV>
    <ACV>
        <N>7Q4</N>
        <C>C0S135</C>
    </ACV>
</ACVS>

New XML (current):

<ACVS>
    <ACV>
        <N>701</N>
        <C>C10S120</C>
    </ACV>
    <ACV>
        <N>735</N>
        <C>S135</C>
    </ACV>
    <ACV>
        <N>736</N>
        <C>C0S135</C>
    </ACV>
    <ACV>
        <N>7Q4</N>
        <C>C0S135</C>
    </ACV>
</ACVS>

Comparison:

Diff fileChanges = DiffBuilder.compare(Input.fromFile(previous))
            .withTest(Input.fromFile(current))
            .ignoreWhitespace()
            .checkForSimilar()
            .build();

fileChanges.getDifferences()

I end up with a number of changes as the elements are matched incorrectly:

  • ACV[1] - N[1]: Expected '735' but was '701'
  • ACV[1] - C[1]: Expected 'S135' but was 'C10S120'
  • ACV[2] - N[1]: Expected '736' but was '735'
  • etc... then:
  • ACV[4]: New Tag added

When I am hoping for a single change:

  • ACV[1]: New Tag added

Is there any way I can achieve this result using XMLUnit?


Solution

  • You want to help XMLUnit understand which ACVs belong together by specifying an ElementSelector that identifies the pairs. But even then you'll end up with two Differences, apart from "new tag added" there will be a "number of children of ACVS is different.

    From looking at your examples you seem to think about your ACVs as identified by the textual content of the N child. This is what you need to tell XMLUnit. The situation is pretty similar to the tr example in https://github.com/xmlunit/user-guide/wiki/SelectingNodes (replace tr with ACV and th with N). You should be able to get the expected result via

    ElementSelectors.conditionalBuilder()
        .whenElementIsNamed("ACV").thenUse(ElementSelectors.byXPath("./N", ElementSelectors.byNameAndText))
        .elseUse(ElementSelectors.byName)
        .build();
    

    or a variation of it.