【问题标题】:Compare XML ignore child order比较 XML 忽略子顺序
【发布时间】:2016-11-01 16:14:30
【问题描述】:

我已经用谷歌搜索过这个问题,我知道还有 10 个类似的问题,但我似乎无法让它发挥作用..

我想比较 2 个 xml 字符串,只得到拼写错误或类似内容的差异,而忽略子顺序。这是我的自动取款机:

    public void xmlCompare() {

    try {
        // First XML-read
        InputStream is = new FileInputStream("xmlTestCorrect.xml");
        String xmlText = IOUtils.toString(is);

        // Second XML-read
        InputStream is2 = new FileInputStream("xmlTestFalse.xml");
        String xmlText2 = IOUtils.toString(is2);

        Diff diff = DiffBuilder.compare(Input.fromString(xmlText)).withTest(Input.fromString(xmlText2))
                .withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byName)).ignoreWhitespace()
                .ignoreComments().checkForSimilar().build();

        System.out.println(diff.hasDifferences());
        System.out.println(diff.getDifferences());

    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

}

我的结果....

 Expected text value 'commons-io' but was 'org.json'
 Expected text value 'commons-io' but was 'json'

等.. 我刚刚在 xmlTestFalse.xml 文件中切换了一些依赖项(还添加了一些成功显示的拼写错误)。并且仍然注意到切换的依赖关系。为什么?? 我尝试做这样的事情,因为我有相同版本的 xmlunit:like this

【问题讨论】:

    标签: java xml xmlunit-2


    【解决方案1】:

    您需要问自己“什么标识了应该相互比较的 XML 树”——然后向 XMLUnit 解释它:-)

    请看https://github.com/xmlunit/user-guide/wiki/SelectingNodes

    您没有显示要比较的 XML,所以我猜它类似于 Maven POM。

    假设你想拥有

    <dependency>
      <groupId>commons-io</groupId>
      <artifactId>commons-io</artifactId>
    </dependency>
    <dependency>
      <groupId>org.json</groupId>
      <artifactId>json</artifactId>
    </dependency>
    

    <dependency>
      <groupId>org.json</groupId>
      <artifactId>json</artifactId>
    </dependency>
    <dependency>
      <groupId>commons-io</groupId>
      <artifactId>commons-io</artifactId>
    </dependency>
    

    作为“相似”结果。

    这里需要意识到的重要一点是您需要选择正确的dependency 元素。如果您尝试匹配正确的 groupId 元素,那就太迟了。一旦 XMLUnit 确定了 dependency 元素,该子树内就只有一个 groupId 元素。

    您已经告诉 XMLUnit 通过元素名称来匹配节点。这意味着 dependency 元素按文档顺序匹配,这不是您想要的。您可能想要“匹配元素名称和名为artifactId 的子元素的文本值”之类的内容。

    不过,对于 POM 的其余部分,这样的选择器将毫无用处。大多数其他元素根本没有artifactId 子元素。这就是条件选择器发挥作用的地方。您需要将ElementSelectors.byName 替换为“更复杂一点”的东西。这个

    ElementSelectors.conditionalBuilder()
       .whenElementIsNamed("dependency")
       .thenUse(ElementSelectors.byXPath("./artifactId",
                                         ElementSelectors.byNameAndText))
       .elseUse(ElementSelectors.byName)
       .build()
    

    应该适用于dependency 和所有“简单”的 XML 元素案例。如果有更复杂的情况,则需要添加更多条件。

    【讨论】:

    • 是的,我认为这是问题所在,因为我尝试使用不太复杂的 xml 文档并且它有效。我会尝试你的解决方案。谢谢你的回答!
    • 我试过这个,它可能会工作。问题是我需要比较大约 300 行的 xml 文件,并且元素有时非常深(最多 3 层)。在所有情况下都很难手动编写它。有没有更简单的方法来做到这一点?也许比较文档的一小部分(节点的节点)或其他东西?
    • 如果没有更简单的规则,对整个文档执行此操作不会变得更简单。 DifferenceEngine 在节点级别工作,因此当然可以比较子树。
    • 嗨@Stefan Bodewig,我遵循了你的想法,但是当我比较两个xml文件时,子节点由conditionalBuilder匹配,我想我失去了一些节点丢失的信息,因为它可以' t 与另一个比较 -> 因此没有差异。你明白我的意思吗?我能以某种方式解决它吗?
    • 对不起,我现在才看到评论。不,即使有条件 ElementSelector,您仍然应该看到 CHILD_LOOKUP 差异,因为这些差异是由差异引擎为根本未匹配的每个节点创建的。
    猜你喜欢
    • 1970-01-01
    • 2023-03-21
    • 1970-01-01
    • 2020-01-19
    • 2013-05-08
    • 1970-01-01
    • 1970-01-01
    • 2012-05-29
    • 2022-01-25
    相关资源
    最近更新 更多