java - 当父节点包含多个具有相同名称和属性列表但属性值不同的子节点时,XMLUnit 比较 XML 不起作用

标签 java xmlunit

我正在使用 XMLUnit 比较两个 XML 以检测更新。我的 pom 如下:

<dependency>
    <groupId>xmlunit</groupId>
    <artifactId>xmlunit</artifactId>
    <version>1.6</version>
</dependency>

对于大多数情况,XMLUnit 工作正常,除了少数情况下给定的差异是错误的或意外的。让我们首先来看 XMLUnit 正常工作的积极场景:

案例 1:

XML 原始:

<ClassHours>                          
    <Hours close="11:10" day="27" classname="sec-1" open="17:20" noOfStudent="23"/>
    <Hours close="11:10" day="28" classname="sec-2" open="17:20" noOfStudent="43"/>
    <Hours close="11:10" day="21" classname="sec-3" open="17:20" noOfStudent="12"/>
    <Hours close="11:10" day="1" classname="sec-4" open="17:20" noOfStudent="54"/>
    <Hours close="11:10" day="25" classname="sec-5" open="17:20" noOfStudent="22"/>
    <Hours close="11:10" day="1" classname="sec-6" open="17:20" noOfStudent="10"/>      s
</ClassHours>

XML 更新:

<ClassHours>                          
    <Hours close="18:00" day="27" classname="sec-1" open="10:00" noOfStudent="23"/>
    <Hours close="18:00" day="28" classname="sec-2" open="10:00" noOfStudent="43"/>
    <Hours close="18:00" day="21" classname="sec-3" open="10:00" noOfStudent="12"/>
    <Hours close="18:00" day="1" classname="sec-4" open="10:00" noOfStudent="54"/>
    <Hours close="18:00" day="25" classname="sec-5" open="10:00" noOfStudent="22"/>
    <Hours close="18:00" day="1" classname="sec-6" open="10:00" noOfStudent="10"/>      s
</ClassHours>

您可以注意到,父节点包含多个子节点。对于所有子节点,名称和属性相同,唯一的区别在于“打开”和“关闭”属性值。在这种情况下,输出是:

2019-12-24 19:53:28,093  INFO [main] (XMLDiffMain.java:107) -  Node [/ClassHours/Hours, node attribute : [close], Before value : [11:10], After value : [18:00]]
2019-12-24 19:53:28,093  INFO [main] (XMLDiffMain.java:107) -  Node [/ClassHours/Hours, node attribute : [open], Before value : [17:20], After value : [10:00]]
2019-12-24 19:53:28,093  INFO [main] (XMLDiffMain.java:107) -  Node [/ClassHours/Hours, node attribute : [close], Before value : [11:10], After value : [18:00]]
2019-12-24 19:53:28,093  INFO [main] (XMLDiffMain.java:107) -  Node [/ClassHours/Hours, node attribute : [open], Before value : [17:20], After value : [10:00]]
2019-12-24 19:53:28,093  INFO [main] (XMLDiffMain.java:107) -  Node [/ClassHours/Hours, node attribute : [close], Before value : [11:10], After value : [18:00]]
2019-12-24 19:53:28,095  INFO [main] (XMLDiffMain.java:107) -  Node [/ClassHours/Hours, node attribute : [open], Before value : [17:20], After value : [10:00]]
2019-12-24 19:53:28,096  INFO [main] (XMLDiffMain.java:107) -  Node [/ClassHours/Hours, node attribute : [close], Before value : [11:10], After value : [18:00]]
2019-12-24 19:53:28,096  INFO [main] (XMLDiffMain.java:107) -  Node [/ClassHours/Hours, node attribute : [open], Before value : [17:20], After value : [10:00]]
2019-12-24 19:53:28,096  INFO [main] (XMLDiffMain.java:107) -  Node [/ClassHours/Hours, node attribute : [close], Before value : [11:10], After value : [18:00]]
2019-12-24 19:53:28,096  INFO [main] (XMLDiffMain.java:107) -  Node [/ClassHours/Hours, node attribute : [open], Before value : [17:20], After value : [10:00]]
2019-12-24 19:53:28,097  INFO [main] (XMLDiffMain.java:107) -  Node [/ClassHours/Hours, node attribute : [close], Before value : [11:10], After value : [18:00]]
2019-12-24 19:53:28,097  INFO [main] (XMLDiffMain.java:107) -  Node [/ClassHours/Hours, node attribute : [open], Before value : [17:20], After value : [10:00]]

案例2:

XML 原始:

<ClassHours>                          
    <Hours close="11:10" day="27" classname="sec-1" open="17:20" noOfStudent="23"/>
    <Hours close="11:10" day="28" classname="sec-2" open="17:20" noOfStudent="43"/>
    <Hours close="11:10" day="21" classname="sec-3" open="17:20" noOfStudent="12"/>
    <Hours close="11:10" day="1" classname="sec-4" open="17:20" noOfStudent="54"/>
    <Hours close="11:10" day="25" classname="sec-5" open="17:20" noOfStudent="22"/>
    <Hours close="11:10" day="1" classname="sec-6" open="17:20" noOfStudent="10"/>      s
</ClassHours>

XML 更新:

<ClassHours>    
    <Hours close="18:00" day="28" classname="sec-2" open="10:00" noOfStudent="43"/>
    <Hours close="18:00" day="21" classname="sec-3" open="10:00" noOfStudent="12"/>
    <Hours close="18:00" day="27" classname="sec-1" open="10:00" noOfStudent="23"/>
    <Hours close="18:00" day="1" classname="sec-4" open="10:00" noOfStudent="54"/>
    <Hours close="18:00" day="25" classname="sec-5" open="10:00" noOfStudent="22"/>
    <Hours close="18:00" day="1" classname="sec-6" open="10:00" noOfStudent="10"/>      s
</ClassHours>

这里,对于所有子节点来说,名称和属性都是相同的,区别在于OpenClose属性值。这次,节点的序列也被更新,因为类名 sec-3 行被移动到 sec-2 之后。在这种情况下,输出是:

2019-12-24 19:54:31,737  INFO [main] (XMLDiffMain.java:107) -  Node [/ClassHours/Hours, node attribute : [classname], Before value : [sec-1], After value : [sec-2]]
2019-12-24 19:54:31,738  INFO [main] (XMLDiffMain.java:107) -  Node [/ClassHours/Hours, node attribute : [close], Before value : [11:10], After value : [18:00]]
2019-12-24 19:54:31,738  INFO [main] (XMLDiffMain.java:107) -  Node [/ClassHours/Hours, node attribute : [day], Before value : [27], After value : [28]]
2019-12-24 19:54:31,738  INFO [main] (XMLDiffMain.java:107) -  Node [/ClassHours/Hours, node attribute : [noOfStudent], Before value : [23], After value : [43]]
2019-12-24 19:54:31,738  INFO [main] (XMLDiffMain.java:107) -  Node [/ClassHours/Hours, node attribute : [open], Before value : [17:20], After value : [10:00]]
2019-12-24 19:54:31,740  INFO [main] (XMLDiffMain.java:107) -  Node [/ClassHours/Hours, node attribute : [classname], Before value : [sec-2], After value : [sec-3]]
2019-12-24 19:54:31,740  INFO [main] (XMLDiffMain.java:107) -  Node [/ClassHours/Hours, node attribute : [close], Before value : [11:10], After value : [18:00]]
2019-12-24 19:54:31,740  INFO [main] (XMLDiffMain.java:107) -  Node [/ClassHours/Hours, node attribute : [day], Before value : [28], After value : [21]]
2019-12-24 19:54:31,741  INFO [main] (XMLDiffMain.java:107) -  Node [/ClassHours/Hours, node attribute : [noOfStudent], Before value : [43], After value : [12]]
2019-12-24 19:54:31,741  INFO [main] (XMLDiffMain.java:107) -  Node [/ClassHours/Hours, node attribute : [open], Before value : [17:20], After value : [10:00]]
2019-12-24 19:54:31,741  INFO [main] (XMLDiffMain.java:107) -  Node [/ClassHours/Hours, node attribute : [classname], Before value : [sec-3], After value : [sec-1]]
2019-12-24 19:54:31,741  INFO [main] (XMLDiffMain.java:107) -  Node [/ClassHours/Hours, node attribute : [close], Before value : [11:10], After value : [18:00]]
2019-12-24 19:54:31,741  INFO [main] (XMLDiffMain.java:107) -  Node [/ClassHours/Hours, node attribute : [day], Before value : [21], After value : [27]]
2019-12-24 19:54:31,741  INFO [main] (XMLDiffMain.java:107) -  Node [/ClassHours/Hours, node attribute : [noOfStudent], Before value : [12], After value : [23]]
2019-12-24 19:54:31,742  INFO [main] (XMLDiffMain.java:107) -  Node [/ClassHours/Hours, node attribute : [open], Before value : [17:20], After value : [10:00]]
2019-12-24 19:54:31,742  INFO [main] (XMLDiffMain.java:107) -  Node [/ClassHours/Hours, node attribute : [close], Before value : [11:10], After value : [18:00]]
2019-12-24 19:54:31,742  INFO [main] (XMLDiffMain.java:107) -  Node [/ClassHours/Hours, node attribute : [open], Before value : [17:20], After value : [10:00]]
2019-12-24 19:54:31,742  INFO [main] (XMLDiffMain.java:107) -  Node [/ClassHours/Hours, node attribute : [close], Before value : [11:10], After value : [18:00]]
2019-12-24 19:54:31,742  INFO [main] (XMLDiffMain.java:107) -  Node [/ClassHours/Hours, node attribute : [open], Before value : [17:20], After value : [10:00]]
2019-12-24 19:54:31,742  INFO [main] (XMLDiffMain.java:107) -  Node [/ClassHours/Hours, node attribute : [close], Before value : [11:10], After value : [18:00]]
2019-12-24 19:54:31,742  INFO [main] (XMLDiffMain.java:107) -  Node [/ClassHours/Hours, node attribute : [open], Before value : [17:20], After value : [10:00]]

这里的输出是错误的,因为差异仅在于值,但 XMLUnit 也考虑了节点的顺序并给出了这样的输出。

我的代码是:

    LOGGER.debug("Comparing Actual and Expected XMLs");
    XMLUnit.setIgnoreWhitespace(true);
    XMLUnit.setIgnoreAttributeOrder(true);
    XMLUnit.setIgnoreComments(true);
    DetailedDiff diff = new DetailedDiff(XMLUnit.compareXML(expectedXML, actualXML));
    diff.overrideElementQualifier(new ElementNameAndAttributeQualifier());

    return diff.getAllDifferences();

有人可以告诉我如何解决这个问题吗?我也尝试过添加

diff.overrideDifferenceListener(new IgnoreTextAndAttributeValuesDifferenceListener());
diff.overrideElementQualifier(new RecursiveElementNameAndTextQualifier());

仍然得到相同的结果。另外,我无法控制 XML 节点的顺序,因为它来自其他一些外部系统。我需要修复在比较节点属性时忽略序列。

此外,我已经提到这是 XMLUnit 无法工作的唯一情况。对于所有其他情况,它都按预期工作。

最佳答案

您正在使用 ElementNameAndAttributeQualifier 的无参数构造函数,这意味着如果两个元素的名称相同且所有属性具有相同的值,则它们有资格进行比较。对于示例中的任何一对元素来说,情况并非如此,因为 close 属性都不同。所以根本没有匹配项。

在 XMLUnit 1.x 中,默认行为是将没有匹配伙伴的元素按文档顺序与测试文档中没有伙伴的元素进行匹配。因此,实际上您是按顺序比较元素。

您可以做的一件事是通过列出您希望在构造函数中保留相同值的属性来使 ElementNameAndAttributeQualifier 更加具体。您可能还想将 XMLUnit.setCompareUnmatched 设置为 false,这样您就不会被错误的默认值绊倒 - 或者更好的是,切换到 XMLUnit 2.x,这与 1 不同.x 是积极维护的,永远不会相互比较不匹配的节点。

关于java - 当父节点包含多个具有相同名称和属性列表但属性值不同的子节点时,XMLUnit 比较 XML 不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59470597/

相关文章:

XMLUnit Compare Xml 比较错误的节点

java - XMLUnit - 比较时忽略 'id' 属性

java - XMLUnit - 比较两个忽略子顺序的 XML

java - Executor Service 和 Rate Limiter

java - 在Java程序中打开Windows虚拟键盘

java - 如何从文件中将字符串读入字符串数组?

java - HQL语法错误

java - 使用 Liferay、SpringMVC 和 @RequestMapping,我是否遗漏了什么?

java - 比较 xml XMLUnit 时忽略某些元素