java - XMLUnit比较XML不起作用,其中父节点包含多个具有相同名称和属性列表但属性值不同的子节点
问题描述
我正在使用 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>
在这里,同样对于所有子节点,名称和属性相同,不同之处在于打开和关闭属性值。这次节点的序列也随着类名 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 不同,它得到积极维护,并且永远不会相互比较不匹配的节点。
推荐阅读
- python - 如何定义一个函数并输入两个正整数,以便当它输入负整数或字符串时会引发 ValueError 但打印出“无效”?
- java - SPEL如何防范注入攻击
- tkinter - 如何将列表框中的项目复制到不同框架中的另一个
- python - Keras weighted_metrics 在计算中不包括样本权重
- hive - 如何将智能表中的数据动态提取到 Hive 表中
- c - 将 volatile 变量与自身进行比较
- wgs84 - 网络墨卡托公式越界?
- logging - 如何查看 ECS Fargate 容器内的日志?
- linux - CMAKE 交叉编译后构建命令
- devexpress - 如何在 Devexpress Gantt 中添加 cellClick 或 Rowclick?