2

我有 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**
 }
4

1 回答 1

1

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

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

如果您的自定义元素选择器按照您的评论所说的那样做,那么您根本不会选择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();

当馈送差分引擎时。

于 2018-03-08T17:12:36.087 回答