在 Java 中使用 xpath 比较忽略某些元素的两个 xml 文件
Compare two xml files ignoring certain elements using xpath in Java
谁能告诉我如何使用 xpath 比较两个忽略某些元素的 xml 文件?
例如,我需要比较下面两个 xml 文件,但需要忽略 'Date' 元素,方法是传递 Xpath(//Set[1]/Product[1]/Date ) 该元素在 运行 期间。要忽略的元素每次都可能不同。
Xml 1:-
<?xml version="1.0" encoding="utf-8"?>
<Set
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="urn:abc:product:v3" xsi:schemaLocation="urn:abc:product:v3 abc.xsd">
<Product>
<id>1</id>
<ref>1</ref>
<Date>2021-09-19</Date>
<company>JJ</company>
<lastModified>2021-09-20T21:00:30</lastModified>
<productOne>
<partProduct>
<Level>3.0</Level>
<Flag>0</Flag>
<Code>EN</Code>
</partProduct>
</productOne>
</Product>
</Set>
Xml 2:-
<?xml version="1.0" encoding="utf-8"?>
<Set
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="urn:abc:product:v3" xsi:schemaLocation="urn:abc:product:v3 abc.xsd">
<Product>
<id>2</id>
<ref>2</ref>
<Date>2021-09-20</Date>
<company>JJ</company>
<lastModified>2021-09-20T21:00:30</lastModified>
<productOne>
<partProduct>
<Level>3.0</Level>
<Flag>0</Flag>
<Code>EN</Code>
</partProduct>
</productOne>
</Product>
</Set>
您需要通过删除要忽略的元素,将两个文件转换为比较相等的形式。您通常会使用 XSLT 来执行此操作。转换后,您可以使用 XPath 2.0 函数 deep-equal() 比较结果,或者将两个文档序列化为规范 XML 并在字符或二进制级别比较文件。
更新
感谢您更清楚地解释问题。
我会通过 运行 XQuery Update 删除路径表达式选择的节点,然后使用 fn:deep-equal() 或通过规范序列化比较生成的文档并比较生成的词汇形式。
作为 XQuery 更新的替代方法,您可以使用 xmlstarlet 或 Saxon 的 Gizmo 工具。
但这可能取决于您希望从比较中得到什么。如果你想要一个 yes/no 的答案,上面的内容很好,但是获取差异的细节更加困难。您可以编写自己的查询来查找差异,或使用诸如 DeltaXML.
之类的工具
如果您使用的是 XmlUnit,那么您可以为节点定义过滤器:
Diff myDiff = DiffBuilder.compare(controlXml)
.withTest(testXml)
// ignore all nodes with 'Date' name
.withNodeFilter(node -> !"Date".equals(node.getNodeName()))
.build();
谁能告诉我如何使用 xpath 比较两个忽略某些元素的 xml 文件?
例如,我需要比较下面两个 xml 文件,但需要忽略 'Date' 元素,方法是传递 Xpath(//Set[1]/Product[1]/Date ) 该元素在 运行 期间。要忽略的元素每次都可能不同。
Xml 1:-
<?xml version="1.0" encoding="utf-8"?>
<Set
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="urn:abc:product:v3" xsi:schemaLocation="urn:abc:product:v3 abc.xsd">
<Product>
<id>1</id>
<ref>1</ref>
<Date>2021-09-19</Date>
<company>JJ</company>
<lastModified>2021-09-20T21:00:30</lastModified>
<productOne>
<partProduct>
<Level>3.0</Level>
<Flag>0</Flag>
<Code>EN</Code>
</partProduct>
</productOne>
</Product>
</Set>
Xml 2:-
<?xml version="1.0" encoding="utf-8"?>
<Set
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="urn:abc:product:v3" xsi:schemaLocation="urn:abc:product:v3 abc.xsd">
<Product>
<id>2</id>
<ref>2</ref>
<Date>2021-09-20</Date>
<company>JJ</company>
<lastModified>2021-09-20T21:00:30</lastModified>
<productOne>
<partProduct>
<Level>3.0</Level>
<Flag>0</Flag>
<Code>EN</Code>
</partProduct>
</productOne>
</Product>
</Set>
您需要通过删除要忽略的元素,将两个文件转换为比较相等的形式。您通常会使用 XSLT 来执行此操作。转换后,您可以使用 XPath 2.0 函数 deep-equal() 比较结果,或者将两个文档序列化为规范 XML 并在字符或二进制级别比较文件。
更新
感谢您更清楚地解释问题。
我会通过 运行 XQuery Update 删除路径表达式选择的节点,然后使用 fn:deep-equal() 或通过规范序列化比较生成的文档并比较生成的词汇形式。
作为 XQuery 更新的替代方法,您可以使用 xmlstarlet 或 Saxon 的 Gizmo 工具。
但这可能取决于您希望从比较中得到什么。如果你想要一个 yes/no 的答案,上面的内容很好,但是获取差异的细节更加困难。您可以编写自己的查询来查找差异,或使用诸如 DeltaXML.
之类的工具如果您使用的是 XmlUnit,那么您可以为节点定义过滤器:
Diff myDiff = DiffBuilder.compare(controlXml)
.withTest(testXml)
// ignore all nodes with 'Date' name
.withNodeFilter(node -> !"Date".equals(node.getNodeName()))
.build();