36

我有这样的 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 以外的库的建议。

4

5 回答 5

39

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

    }
}
于 2009-08-06T23:29:09.910 回答
26

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

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

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

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

于 2016-05-25T15:56:03.540 回答
9

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

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

于 2009-08-06T23:18:45.783 回答
3

您现在可以${xmlunit.ignore}在 XMLUnit 2.6.0 中尝试(添加依赖项 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>

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

于 2018-06-26T06:38:59.613 回答
0

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

这只是一个带有两个 xml 作为字符串的 XMLdiff 方法

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;
    }

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

于 2021-06-23T12:01:13.213 回答