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

时间:2009-08-06 21:27:33

标签: java xml junit xmlunit

我有一条XML消息:

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

我想将由测试方法生成的此类消息与预期消息进行比较,但我不关心elementA。所以,我希望上述消息被认为是等同于:

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

我正在使用最新版本的XMLUnit

我想象答案涉及创建自定义DifferenceListener;如果有可以在那里使用的话,我只是不想重新发明轮子。

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

6 个答案:

答案 0 :(得分:38)

我最终实现了一个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) {

    }
}

答案 1 :(得分:15)

由于这个问题得到了回答,XMLUnit的情况发生了很大的变化。

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

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

如果您再调用documentDiff.hasDifferences(),则会忽略添加到过滤器的节点。

答案 2 :(得分:8)

我会使用XSLT和identity transform过滤掉我想忽略的元素,并比较结果。

早些时候参见XSL: how to copy a tree, but removing some nodes ?

答案 3 :(得分:0)

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

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

期望的XML:

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

实际XML:

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

请注意,从unit tests可以看出,目前$ {xmlunit.ignore}仅支持文本节点和属性值无知。

答案 4 :(得分:0)

让我们简单一点,忽略节点,无论您要忽略多少个节点,或者如果您不知道要忽略多少个节点 ,请按照以下简单步骤操作

这只是一个 XMLdiff 方法,将两个 xml 作为字符串

public static void XMLdiff(String XML1, String XML2){
               
 //nodes you wanted to ignore
        String[] ignoreNodes = {"nodeX", "nodeY", "nodeZ"};
      
//testnode(node,ignoreNodes) is handled below for finding and ignoring multiple nodes
        final Diff documentDiff = DiffBuilder.compare(XML1)
                                  .withTest(XML2)
                                  .withNodeFilter(node->testnode(node,ignoreNodes))
                                  .build();
}

private static boolean testnode(Node node, String[] name) {

        for (int i = 0; i < name.length; i++) {

            if (node.getNodeName().toString().equals(name[i])) {
                return false;
            }
            if (name.length == 0) {
                break;
            }
        }
        return true;
    }

从此链接添加依赖项或 jar https://www.xmlunit.org/

答案 5 :(得分:-1)

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) {

    }
}

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