在 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();