Java 比较 XML 时如何忽略某些元素?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1241593/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 07:21:24  来源:igfitidea点击:

How do I ignore certain elements when comparing XML?

javaxmljunitxmlunit

提问by Paul Morie

I have an XML message like so:

我有一个像这样的 XML 消息:

<root>
  <elementA>something</elementA>
  <elementB>something else</elementB>
  <elementC>yet another thing</elementC>
</root>

I want to compare a message of this type produced by a method under test to an expected message, but I don't care about elementA. So, I'd like the above message to be considered equal to:

我想将被测方法产生的这种类型的消息与预期的消息进行比较,但我不关心elementA. 因此,我希望将上述消息视为等于:

<root>
  <elementA>something different</elementA>
  <elementB>something else</elementB>
  <elementC>yet another thing</elementC>
</root>

I'm using the latest version of XMLUnit.

我正在使用最新版本的XMLUnit

I'm imagining that the answer involves creating a custom DifferenceListener; I just don't want to reinvent the wheel if there's something ready to use out there.

我想象答案涉及创建自定义DifferenceListener; 如果有可用的东西,我只是不想重新发明轮子。

Suggestions that use a library other than XMLUnit are welcome.

欢迎提出使用 XMLUnit 以外的库的建议。

采纳答案by Jean-Fran?ois Savard

Things have changed a lot for XMLUnitsince this question was answered.

自从回答了这个问题以来,XMLUnit 的情况发生了很大变化。

You can now easily ignore a node when using a DiffBuilder:

您现在可以在使用时轻松忽略节​​点DiffBuilder

final Diff documentDiff = DiffBuilder
            .compare(expectedSource)
            .withTest(actualSource)
            .withNodeFilter(node -> !node.getNodeName().equals(someName))
            .build();

If you then call documentDiff.hasDifferences()nodes added to filter will be ignored.

如果然后调用documentDiff.hasDifferences()添加到过滤器的节点将被忽略。

回答by lavinio

I would use XSLT and the identity transformto filter out elements I want to ignore, and compare the results.

我会使用 XSLT 和身份转换来过滤掉我想要忽略的元素,并比较结果。

See XSL: how to copy a tree, but removing some nodes ?earlier on SO.

请参阅XSL:如何复制树,但删除一些节点?早些时候在 SO 上。

回答by Paul Morie

I wound up implementing a DifferenceListenerthat takes a list of node names (with namespaces) to ignore textual differences for:

我最终实现了一个DifferenceListener采用节点名称列表(带有命名空间)来忽略以下文本差异的方法:

public class IgnoreNamedElementsDifferenceListener implements DifferenceListener {
    private Set<String> blackList = new HashSet<String>();

    public IgnoreNamedElementsDifferenceListener(String ... elementNames) {
        for (String name : elementNames) {
            blackList.add(name);
        }
    }

    public int differenceFound(Difference difference) {
        if (difference.getId() == DifferenceConstants.TEXT_VALUE_ID) {
            if (blackList.contains(difference.getControlNodeDetail().getNode().getParentNode().getNodeName())) {
                return DifferenceListener.RETURN_IGNORE_DIFFERENCE_NODES_IDENTICAL;
            }
        }

        return DifferenceListener.RETURN_ACCEPT_DIFFERENCE;
    }

    public void skippedComparison(Node node, Node node1) {

    }
}

回答by juniper

public class IgnoreNamedElementsDifferenceListener implements DifferenceListener {
    private Set<String> blackList = new HashSet<String>();

    public IgnoreNamedElementsDifferenceListener(String ... elementNames) {
        for (String name : elementNames) {
            blackList.add(name);
        }
    }

    public int differenceFound(Difference difference) {
        if (difference.getId() == DifferenceConstants.TEXT_VALUE_ID) {
            if (blackList.contains(difference.getControlNodeDetail().getNode().getParentNode().getNodeName())) {
                return DifferenceListener.RETURN_IGNORE_DIFFERENCE_NODES_IDENTICAL;
            }
        }

        return DifferenceListener.RETURN_ACCEPT_DIFFERENCE;
    }

    public void skippedComparison(Node node, Node node1) {

    }
}

How to invoke this own implementation to my method to see the differences after the specific node ignored for the comparison.?

如何在我的方法中调用这个自己的实现以查看忽略特定节点进行比较后的差异。?

回答by Zheng Wang

You can now try ${xmlunit.ignore}in XMLUnit 2.6.0 (add dependency xmlunit-placeholders). Sample code is as below.

您现在可以${xmlunit.ignore}在 XMLUnit 2.6.0 中尝试(添加依赖关系 xmlunit-placeholders)。示例代码如下。

Diff diff = DiffBuilder
    .compare(expectedXML)
    .withTest(actualXML)
    .withDifferenceEvaluator(new PlaceholderDifferenceEvaluator())
    .build();

Expected XML:

预期的 XML:

<root>
  <elementA>${xmlunit.ignore}</elementA>
  <elementB>something else</elementB>
  <elementC>yet another thing</elementC>
</root>

Actual XML:

实际的 XML:

<root>
  <elementA>anything</elementA>
  <elementB>something else</elementB>
  <elementC>yet another thing</elementC>
</root>

Do notice that currently the ${xmlunit.ignore} only supports text node and attribute value ignorance, as can be seen from the unit tests.

请注意,当前 ${xmlunit.ignore} 仅支持文本节点和属性值无知,从单元测试中可以看出。