【问题标题】:Compare two xml files ignoring certain elements using xpath in Java在 Java 中使用 xpath 比较忽略某些元素的两个 xml 文件
【发布时间】:2022-12-29 00:38:07
【问题描述】:

我如何比较两个 XML 文件,使用 XPath 忽略某些元素?

例如,我需要比较以下两个 XML 文件,但我需要通过在运行期间传递此元素的 Xpath(//Set[1]/Product[\1]/Date) 来忽略“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>

【问题讨论】:

    标签: java xml doc xmlunit


    【解决方案1】:

    您需要通过删除要忽略的元素,将两个文件转换为它们比较相等的形式。您通常会使用 XSLT 来执行此操作。转换后,您可以使用 XPath 2.0 函数 deep-equal() 比较结果,或者将两个文档序列化为规范 XML 并在字符或二进制级别比较文件。

    更新

    感谢您更清楚地解释这个问题。

    为此,我将运行 XQuery Update 以删除路径表达式选择的节点,然后使用 fn:deep-equal() 比较生成的文档,或通过执行规范序列化并比较生成的词法形式。

    作为 XQuery 更新的替代方法,您可以使用 xmlstarlet 或 Saxon 的 Gizmo 工具。

    但这可能取决于您希望从比较中得到什么。如果你想要一个是/否的答案,上面的内容很好,但是获取差异的细节更加困难。您可以编写自己的查询来查找差异,或使用诸如 DeltaXML 之类的工具。

    【讨论】:

    • 问题是我提供的 xpath 不一样。每次都可能不同
    • 如果您提出更多信息性问题,您可能会得到更多信息性答案。
    • 对不起,我应该的。现在完成。
    • 无论如何,我可以只搜索元素,将其删除,然后将更新后的 xml 保存为新文档,甚至将其保存到原始文档中吗?从那里,我可以进行比较
    • 我建议了三种方法:XQuery 更新、xmlstarlet 或 Gizmo。如果您在使用这些工具中的任何一个时遇到问题,请提出一个新问题——如果您尝试在原始线程上提出补充问题,那么 SO 不会很好地工作。
    【解决方案2】:

    如果您使用的是 XmlUnit,则可以为节点定义过滤器:

    Diff myDiff = DiffBuilder.compare(controlXml)
        .withTest(testXml)
        // ignore all nodes with 'Date' name
        .withNodeFilter(node -> !"Date".equals(node.getNodeName()))
        .build();
    

    【讨论】:

      最近更新 更多