比较XML文件时,XmlUnit忽略元素的顺序

时间:2019-09-05 16:20:13

标签: java xml java-8 diff xmlunit-2

我有以下两个xml文件:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<pricebooks xmlns="http://www.blablabla.com">
    <pricebook>
        <header pricebook-id="my-id">
            <currency>GBP</currency>
            <display-name xml:lang="x-default">display name</display-name>
            <description>my description 1</description>
        </header>
        <price-tables>
            <price-table product-id="id1" mode="mode1">
                <amount quantity="1">30.00</amount>
            </price-table>
            <price-table product-id="id2" mode="mode2">
                <amount quantity="1">60.00</amount>
            </price-table>
        </price-tables>
    </pricebook>
</pricebooks>

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<pricebooks xmlns="http://www.blablabla.com">
    <pricebook>
        <header pricebook-id="my-id">
            <currency>GBP</currency>
            <display-name xml:lang="x-default">display name</display-name>
            <description>my description 1</description>
        </header>
        <price-tables>
            <price-table product-id="id2" mode="mode2">
                <amount quantity="1">60.00</amount>
            </price-table>
            <price-table product-id="id1" mode="mode1">
                <amount quantity="1">30.00</amount>
            </price-table>
        </price-tables>
    </pricebook>
</pricebooks>

我试图比较忽略元素price-table的顺序,所以对我来说,这两个是相等的。我正在使用

        <dependency>
            <groupId>org.xmlunit</groupId>
            <artifactId>xmlunit-core</artifactId>
            <version>2.5.0</version>
        </dependency>

和下面的代码,但我无法使其工作。它抱怨是因为属性值id1id2不同。

Diff myDiffSimilar = DiffBuilder
    .compare(expected)
    .withTest(actual)
    .checkForSimilar()
    .ignoreWhitespace()
    .ignoreComments()
    .withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byNameAndText))
    .build();
assertFalse(myDiffSimilar.hasDifferences());

我还尝试如下编辑nodeMatcher:

.withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.conditionalBuilder()
    .whenElementIsNamed("price-tables")
    .thenUse(ElementSelectors.byXPath("./price-table", ElementSelectors.byNameAndText))
    .elseUse(ElementSelectors.byName)
    .build()))

谢谢您的帮助。

1 个答案:

答案 0 :(得分:0)

我在您的price-table元素中根本看不到任何嵌套文本,因此byNamAndText仅在元素名称上匹配-所有price-table都相同,因此不相同做你想做的事。

在您的示例中,price-tables没有歧义,因为反正只有一个。因此byXPath方法看起来是错误的。至少在您的摘要中,除了byName元素之外,XMLUnit应该可以与price-table一起使用。

我不确定是否单独使用product-id来标识您的price-table元素或所有属性的组合。 byNameAndAttributes("product-id")或其表亲byNameAndAllAttributes应该起作用。

如果仅 product-id,则对于根本不具有任何byNameAndAttributes("product-id")属性的所有元素,byName变为product-id。在这种特殊情况下,byNameAndAttribute("product-id")可以单独为您处理整个文档,正如我们所见-或多或少是偶然的。

如果您需要比price-table更复杂的规则来其他元素,或者您想要使事情更明确些

ElementSelectors.conditionalBuilder()
    .whenElementIsNamed("price-table")
    .thenUse(ElementSelectors.byNameAndAttributes("product-id"))
    // more special cases
    .elseUse(ElementSelectors.byName)

是更好的选择。