javaxmlxmlunit

Compare a dynamically changing XML using XMLUnit


Currently I'm using XMLunit for testing. I have two XML as below. XML1

<envelope>
<NameValuePairs>
<Name>Karthick</Name>
<value>yes</value>
</NameValuePairs>
<NameValuePairs>
<Name>Anu</Name>
<value>yes</value>
</NameValuePairs>
<NameValuePairs>
<Name>Annie</Name>
<value>No</value>
</NameValuePairs>
<NameValuePairs>
<Name>Aishu</Name>
<value>No</value>
</NameValuePairs>
</envelope>

XML2

<envelope>
    <NameValuePairs>
        <Name>Annie</Name>
        <value>yes</value>
    </NameValuePairs>
    <NameValuePairs>
        <Name>Aishu</Name>
        <value>yes</value>
    </NameValuePairs>
    <NameValuePairs>
        <Name>Karthick</Name>
        <value>No</value>
    </NameValuePairs>
    <NameValuePairs>
        <Name>Anu</Name>
        <value>No</value>
    </NameValuePairs>
</envelope>

Issue 1: as seen in above example, the node "nameValuePair" changes dynamically every time. XMLUnit considers that as difference.
Issue 2:
even though the node "name" changes and "value" is either yes or no, XMLUnit doesn't identify it as difference.

please suggest me a way to compare these kind of XML.


Solution

  • From your description I understand you consider those NameValuePairs elements the same that have a Name child element with the same nested text. And you want XMLUnit to ignore the order of NameValuePairs instances as long as it picks the "correct" pairs by above definition. Is this correct?

    If so, you need to tell XMLUnit which NameValuePairss are the ones to compare with each other, which is the job of the ElementSelector (assuming XMLUnit 2.x here). Your example really is the same as the tr example in XMLUnit's User Guide and I'd encourage you to go there for the full details.

    Whenever XMLUnit encounters a group of sibling elements, the ElementSelector is consulted to decide which branches to compare with each other. Once the branches have been chosen, there is no way back. I.e. when XMLUnit decides to compare the NameValuePairs elements in document order it will never look at the Name element in a different branch than the one it is currently in. This means you need to tell XMLUnit which branches to pick as high up in the document hierarchy as needed.

    In your case you do have a single envelope so the ElementSelector doesn't really matter as long as it is willing to compare the only elements that are there. The children of NameValuePairs all have different element names, so ElementSelectors.byName will work for them - as well as for envelope.

    Translating my first sentence "you consider those NameValuePairs elements the same that have a Name child element with the same nested text" into XMLUnit's built-in ElementSelectors I end up with ElementSelectors.byXPath("./Name", ElementSelectors.byNameAndText) (where the byName part in byNameAndText is somewhat redundant as the XPath already ensures the names are the same). Putting this together you need to use an ElementSelector of

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

    With that XMLUnit should match the NameValuePairs even if they are not in order and detect if the Value elements of the "matching pairs" have changing nested texts.