【发布时间】:2020-04-15 15:27:33
【问题描述】:
我正在使用 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>
这里,对于所有的子节点,名称和属性都是相同的,区别在于Open和Close属性值。这次节点的顺序也随着类名 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 不工作的唯一情况。对于所有其他情况,它都按预期工作。
【问题讨论】:
-
恕我直言 XmlUnit 是正确的;如果您在文本中切换段落,您也不会认为它们相同,对吗?经验法则:如果一个父元素中有多个相同类型的元素,那么顺序很重要;如果父元素中有不同的元素,顺序无关紧要。