Search code examples
java.netxmlxmlunitxmlunit-2

Matching nested elements with different order and number format


I'm using xmlunit 2.2.1 with Java and have the following XMLs to match. The problem here is twofold:

  1. the order is not the same
  2. some of the numerical values may have trailing zeroes (e.g. 0.250000)

For this reason ByNameAndTextRecSelector() doesn't work because it requires all the text nodes to be exact matches, which not the case here. I already implemented a DifferenceEvaluator that will take care of the trailing zeroes in the numbers. But what do I use to select the right elements to compare?

XML 1:

<test>
  <table>
    <row>
      <element>
        <code>ALPHA</code>
        <scale>0.25</scale>
      </element>
    </row>
    <row>
      <element>
        <code>DELTA</code>
        <scale>0.1</scale>
      </element>
    </row>
  </table>
</test>

XML 2:

<test>
  <table>
    <row>
      <element>
        <code>DELTA</code>
        <scale>0.1</scale>
      </element>
    </row>
    <row>
      <element>
        <code>ALPHA</code>
        <scale>0.2500000</scale>
      </element>
    </row>
  </table>
</test>

Solution

  • Is the code element enough to select the correct nodes? If so, an approach like the user guide example https://github.com/xmlunit/user-guide/wiki/SelectingNodes#conditional-elementselectors should work.

    ElementSelectors.conditionalBuilder()
        .whenElementIsNamed("row").thenUse(ElementSelectors.byXPath("./element/code", ElementSelectors.byNameAndText))
        .elseUse(ElementSelectors.byName)
        .build();
    

    This will not help against the different number formats. To deal with them you must override the DifferenceEvaluator and detect the Text nodes that hold numbers, parse them and mark the differences as EQUAL if they are close enough.

    If code is not enough, then you will need to write an ElementSelector that takes care of the numbers like the DifferenceEvaluator I described above and combine that with ElementSelectors.byNameAndText inside the conditional above.