比较XML,忽略元素顺序

10

使用XMLUnit 2,如何比较两个文档并忽略元素顺序?

我看到了这个针对XMLUnit 1的问题,但显然v2中的新API不再具有该方法。

以下是我的当前代码:

Diff diff = DiffBuilder.compare(expected)
            .withTest(actual)
            .ignoreComments()
            .ignoreWhitespace()
            .checkForSimilar()
            .build();

assertFalse(diff.hasDifferences());

针对 Stefan Bodewig 评论的编辑:

这是我在上面片段中进行比较的两个字符串:

String expected = "<root><foo>FOO</foo><bar>BAR</bar></root>";
String actual = "<root><bar>BAR</bar><foo>FOO</foo></root>";

报告的差异

Expected element tag name 'foo' but was 'bar' - comparing <foo...> at /root[1]/foo[1] to <bar...> at /root[1]/bar[1] (DIFFERENT)
Expected text value 'FOO' but was 'BAR' - comparing <foo ...>FOO</foo> at /root[1]/foo[1]/text()[1] to <bar ...>BAR</bar> at /root[1]/bar[1]/text()[1] (DIFFERENT)
Expected element tag name 'bar' but was 'foo' - comparing <bar...> at /root[1]/bar[1] to <foo...> at /root[1]/foo[1] (DIFFERENT)
Expected text value 'BAR' but was 'FOO' - comparing <bar ...>BAR</bar> at /root[1]/bar[1]/text()[1] to <foo ...>FOO</foo> at /root[1]/foo[1]/text()[1] (DIFFERENT)

新的API默认应该忽略元素顺序(这就是DifferenceEvaluators.DEFAULT的作用)。您确定您看到的是差异,而不是其他什么吗? - Stefan Bodewig
我复制了OP的问题,即使我添加了.checkForSimilar()。这似乎与 https://github.com/xmlunit/user-guide/wiki/DifferenceEvaluator#default-differenceevaluator 中的文档相矛盾。下面描述的添加.withNodeMatcher()解决了这个问题。 - Charles Roth
2个回答

14

需要在2.x文档中更加明确的区别是默认的ElementSelector——大致上相当于1.x中的ElementQualifier。在1.x中,默认按名称匹配元素,而在2.x中,默认按顺序匹配元素。也许这是一个不好的想法。

如果您切换到按元素名称匹配,则应该可以使用您的差异。

.withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byName))


谢谢你,Stefan! - Charles Roth
@stefan...如果节点在XML文件中的不同位置,这个能行得通吗? - Abhijit Bashetti
取决于不同的含义。它适用于相同父元素的兄弟节点。否则,您需要确保在考虑元素本身之前,正在比较“正确的父”元素。 XMLUnit从文档树的根开始选择分支进行比较,一旦选择了一个分支作为“匹配项”,XMLUnit将不会查看其他分支。 - Stefan Bodewig
你可能想要使用 Github 的问题(issue)来处理这个。 - Stefan Bodewig

0

你可能需要添加类似以下的内容

.withDifferenceEvaluator(((comparison, outcome) -> {
    if (outcome == ComparisonResult.DIFFERENT && 
        comparison.getType() == ComparisonType.CHILD_NODELIST_SEQUENCE) {
           return ComparisonResult.EQUAL;
    }
return outcome;
})).build();

针对您的Diff构建器

对于我来说,上述解决方案将无法工作,因为compareNodeLists在DOMDifferenceEngine.compareNodes()中已经硬编码了此内容。

new Comparison(ComparisonType.CHILD_NODELIST_SEQUENCE...

我已经为此提出了一张新的工单,但请记住这可能只是因为我理解不足 :-)

https://github.com/xmlunit/xmlunit/issues/258


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接