【问题标题】:XMLUnit comparing ignoring the order of elementsXMLUnit比较忽略元素的顺序
【发布时间】:2018-08-16 14:16:30
【问题描述】:

我有 2 个 XML。我一直在使用 XMLUnit 来比较 2 个 xml 字符串。问题是我无法忽略元素出现的顺序。我尝试覆盖 ElementQualifier 以及 DifferenceListener 但这对这种情况没有帮助。

控制 XML

<xs:complexType>
    <xs:anotation>
        <xs:description>
            <Description>Country</Description>
        </xs:description>
    </xs:anotation>
    <xs:sequence>
        <xs:element name="name" type="xs:string"/>
        <xs:element name="address" type="xs:string"/>
        <xs:element name="city" type="xs:string"/>
        <xs:element name="country" type="xs:string"/>
    </xs:sequence>
</xs:complexType>

测试 XML

<xs:complexType>
    <xs:anotation>
        <xs:description>
            <Description>Country</Description>
        </xs:description>
    </xs:anotation>
    <xs:sequence>
        <xs:element name="name" type="xs:string"/>
        <xs:element name="address" type="xs:string"/>
    </xs:sequence>
    <xs:sequence>
        <xs:element name="name" type="xs:string"/>
        <xs:element name="address" type="xs:string"/>
        <xs:element name="city" type="xs:string"/>
        <xs:element name="street" type="xs:string"/>
    </xs:sequence>
</xs:complexType>

请注意,在 Test XML 中添加了另一个序列,并删除了第一个序列的最后一个元素(国家)。

XMLUnit 抱怨在第二个序列中没有名为city 的元素。它按顺序排列元素。我尝试了覆盖 ELementNameAndAttributeQualifier 但没有产生预期的结果。此外,覆盖 RecursiveElemenNameAndTextQualifier 也没有帮助。 RecursiveElemenNameAndTextQualifier 不起作用的原因是第一个序列没有匹配项。我将如何接近并确保

public boolean qualifyForComparison(Element element, Element element1) 
{
       // should return true only when **element 1** has all elements of  **element**
 }

【问题讨论】:

    标签: java xsd xmlunit xmlunit-2


    【解决方案1】:

    这确实比“忽略元素顺序”复杂一点,不是吗? :-)

    ElementNameAndAttributeQualifier 可以用于 xs:element 元素,但您真正的问题是让 XMLUnit 选择正确的 xs:sequence 元素。我真的建议您使用 XMLUnit 2.x,因为它的条件元素选择器构建器是您需要的,而在 XMLUnit 1.x 中复制它有点麻烦。

    如果您的自定义元素选择器按照您的 cmets 所说的进行,那么您根本不会选择要比较的 xs:sequence 元素。 “测试”序列不包含“街道”xs:element,而 ElementNameQualifier 将返回 false。

    我不太确定您想要的确切逻辑是什么样的。您在评论中描述的内容类似于(使用 XMLUnit 2.x,未经测试)

    public boolean canBeCompared(Element e1, Element e2) {
        NodeList e1Children = e1.getChildNodes();
        NodeList e2Children = e2.getChildNodes();
        Iterable<Map.Entry<Node, Node>> matches =
            new DefaultNodeMatcher(ElementSelectors.byNameAndAllAttributes)
            .match(new IterableNodeList(e1Children), new IterableNodeList(e2Children));
        for (Map.Entry<Node, Node> m : matches) {
            if (m.getKey() == null // test child with no matching control child
                || m.getValue() == null // control child with no matching test child
            ) {
                return false;
            }
        }
        return true;
    }
    

    没有内置的方法可以做到这一点,您确实需要自己处理 DOM。

    最后你会使用类似的东西

    ElementSelectors.conditionalBuilder()
        .whenElementIsNamed(new QName("sequence", XMLConstants.W3C_XML_SCHEMA_NS_URI))
        .thenUse(the element selector built above)
        .elseUse(ElementSelectors.byNameAndAllAttributes)
        .build();
    

    当输入差异引擎时。

    【讨论】:

    • 感谢您的回答。有什么方法可以根据我们的需要覆盖 ElementSelectors.byNameAndAllAttributes
    • 当然,这正是我猜你需要的。您可以提供ElementSelector 的任何实现。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多