问题
I am using XMLUnit2 to compare 2 XMLs which don't have elements in the same order. I am seeing the below error -
Differences = Expected child 'billingCode' but was 'null' - comparing at /translateServiceRequestResponse[1]/translateServiceRequestReturn[1]/legacyCode[2]/billingCode[1] to NULL
Code
Diff myDiff = DiffBuilder.compare(controlResponse).ignoreWhitespace().ignoreComments().withTest(testResponse).withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byNameAndText)).checkForSimilar().build();
System.out.println("Differences = " + myDiff.toString());
Control File
<translateServiceRequestResponse>
<translateServiceRequestReturn>
<legacyCode>
<amount>0</amount>
<billingCode>VS128</billingCode>
<description>HD Rec</description>
<priceName>EquipChoice X1 HD TP</priceName>
<pricingElementName>X1 HD Receiver</pricingElementName>
<codeAmount>0</codeAmount>
<lobSubType>0</lobSubType>
<addressable>1</addressable>
<nonStandard>false</nonStandard>
</legacyCode>
<legacyCode>
<amount>0</amount>
<billingCode>VF123</billingCode>
<description>HD Rec</description>
<packageCode>VE286</packageCode>
<priceName>EquipChoice X1 HD TP</priceName>
<pricingElementName>X1 HD Receiver</pricingElementName>
<codeAmount>0</codeAmount>
<lobSubType>0</lobSubType>
<addressable>1</addressable>
<nonStandard>false</nonStandard>
</legacyCode>
<legacyCode>
<amount>0</amount>
<billingCode>VF170</billingCode>
<description>HD Rec</description>
<packageCode>VE286</packageCode>
<priceName>EquipChoice X1 HD TP</priceName>
<pricingElementName>X1 HD Receiver</pricingElementName>
<codeAmount>2.5</codeAmount>
<lobSubType>0</lobSubType>
<addressable>1</addressable>
<nonStandard>false</nonStandard>
</legacyCode>
</translateServiceRequestReturn>
Test File
<translateServiceRequestResponse>
<translateServiceRequestReturn>
<legacyCode>
<amount>0</amount>
<billingCode>VS128</billingCode>
<description>HD Rec</description>
<priceName>EquipChoice X1 HD TP</priceName>
<pricingElementName>X1 HD Receiver</pricingElementName>
<codeAmount>0</codeAmount>
<lobSubType>0</lobSubType>
<addressable>1</addressable>
<nonStandard>false</nonStandard>
</legacyCode>
<legacyCode>
<amount>0</amount>
<billingCode>VF170</billingCode>
<description>HD Rec</description>
<packageCode>VE286</packageCode>
<priceName>EquipChoice X1 HD TP</priceName>
<pricingElementName>X1 HD Receiver</pricingElementName>
<codeAmount>2.5</codeAmount>
<lobSubType>0</lobSubType>
<addressable>1</addressable>
<nonStandard>false</nonStandard>
</legacyCode>
<legacyCode>
<amount>0</amount>
<billingCode>VF123</billingCode>
<description>HD Rec</description>
<packageCode>VE286</packageCode>
<priceName>EquipChoice X1 HD TP</priceName>
<pricingElementName>X1 HD Receiver</pricingElementName>
<codeAmount>0</codeAmount>
<lobSubType>0</lobSubType>
<addressable>1</addressable>
<nonStandard>false</nonStandard>
</legacyCode>
</translateServiceRequestReturn>
回答1:
XMLUnit uses the ElementSelector
in order to determine which elements of two sets of siblings in the control and test documents to match with each other. It will start matching from the root of the documents and you must ensure it picks the correct branches at each level. Once a decision has been made, XMLUnit won't back-track.
When picking an ElementSelector
you must always ensure it helps XMLUnit to take the correct branch as close to the root of the document as the logical structure of your document requires. The elements you say are not in the same order are the legacyCode
elements, so you must help XMLUnit to make the correct selection among them. byNameAndText
won't help here. There is no nested text in byNameAndText
at all, so they are all the same and XMLUnit matches the elements in document order.
This is exactly the same problem as the one about tr
s in https://github.com/xmlunit/user-guide/wiki/SelectingNodes
To me looks as if your legacyCode
would be identified by the text nested into the billingCode
element. If so you could use an ElementSelector
like
ElementSelectors.conditionalBuilder()
.whenElementIsNamed("legacyCode").thenUse(ElementSelectors.byXPath("./billingCode", ElementSelectors.byNameAndText))
.elseUse(ElementSelectors.byName)
.build();
You may need to adapt this so it works for parts of the of the document you haven't shown or if byNameAndText
really is required rather than byName
for some other parts of the tree.
来源:https://stackoverflow.com/questions/44064675/xmlunit-issue-comparing-to-xmls-that-are-not-in-same-order