【问题标题】:XMLUnit - Issue comparing to XMLs that are not in same orderXMLUnit - 与顺序不同的 XML 进行比较的问题
【发布时间】:2017-05-19 08:05:15
【问题描述】:

我正在使用 XMLUnit2 来比较 2 个没有相同顺序元素的 XML。我看到以下错误 -

差异 = 预期的子 'billingCode' 但为 'null' - 比较 在 /translateServiceRequestResponse[1]/translateServiceRequestReturn[1]/legacyCode[2]/billingCode[1] 为 NULL

代码

Diff myDiff = DiffBuilder.compare(controlResponse).ignoreWhitespace().ignoreComments().withTest(testResponse).withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byNameAndText)).checkForSimilar().build();
System.out.println("Differences = " + myDiff.toString());

控制文件

<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>

测试文件

<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>

【问题讨论】:

    标签: java xmlunit xmlunit-2


    【解决方案1】:

    XMLUnit 使用ElementSelector 来确定控制和测试文档中两组同级的哪些元素相互匹配。它将从文档的根开始匹配,您必须确保它在每个级别选择正确的分支。一旦做出决定,XMLUnit 将不会回溯。

    在选择ElementSelector 时,您必须始终确保它可以帮助 XMLUnit 根据文档的逻辑结构要求将正确的分支尽可能靠近文档的根。你说的顺序不一样的元素是legacyCode元素,所以你必须帮助XMLUnit在其中做出正确的选择。 byNameAndText 在这里无济于事。 byNameAndText 中根本没有嵌套文本,所以它们都是相同的,并且 XMLUnit 按照文档顺序匹配元素。

    这与https://github.com/xmlunit/user-guide/wiki/SelectingNodes中关于trs的问题完全相同

    在我看来,您的legacyCode 似乎可以通过嵌套在billingCode 元素中的文本来识别。如果是这样,您可以使用 ElementSelector 之类的

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

    您可能需要对此进行调整,使其适用于您未显示的文档部分,或者如果确实需要 byNameAndText 而不是 byName 用于树的其他部分。

    【讨论】:

    • 谢谢斯蒂芬。我有许多类似于这里列出的 legacyCode 的元素。我应该按名称指定它们中的每一个,还是有一种通用的方法来制定它。感谢您的帮助!
    • whenElementIsNamed 旁边还有when,它接受Predicate&lt;Node&gt;。如果有一条规则可以指定选择所有元素,则可以使用它。
    • 再次感谢,斯蒂芬。可以举个例子吗?
    • 取决于你的元素有什么共同点。假设您有一组元素名称 NAMES 并且可以执行类似 ElementSelectors.conditionalBuilder().when(e -&gt; NAMES.contains(Nodes.getQName(e).getLocalPart())).thenUse(...) 的操作。如果要查找的始终是不同的子元素,那么您可能必须明确拼出所有元素和子元素。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多