【问题标题】:XML file comparison in JAVA ignoring node orderJAVA中的XML文件比较忽略节点顺序
【发布时间】:2020-01-19 10:39:05
【问题描述】:

我想使用JAVA 比较xml 文件并检查它们是否“等效”。 以下代码在 2 种情况下适用于我:

  1. 当xml文件完全相同时。
  2. 当xml文件有差异时

但在以下情况下失败:

  1. XML 文件包含相同的节点,但它们的顺序不同。

一个名为Sample.xml 的文件,其内容为:

<Employee>
    <FirstName>Jack</FirstName>
    <LastName>Dave</LastName>
    <Age>21</Age>
    <Professtion>Doctor</Professtion>
</Employee>

另一个名为 Sample1.xml 的文件的内容为:

<Employee>
    <Age>21</Age>
    <Professtion>Doctor</Professtion>
    <FirstName>Jack</FirstName>
    <LastName>Dave</LastName>
</Employee>

注意内容相同,但顺序不同。

我尝试了 [this1],但它对我不起作用。

我尝试的代码如下:

import java.io.BufferedReader;
import java.io.FileReader;
import java.util.List;

import org.custommonkey.xmlunit.DetailedDiff;
import org.custommonkey.xmlunit.Diff;
import org.custommonkey.xmlunit.XMLUnit;
import org.custommonkey.xmlunit.examples.RecursiveElementNameAndTextQualifier;

public class CompareXML {

    public static void main(String[] args) {

        try (BufferedReader bufferedReaderExistingFile = new BufferedReader(new FileReader("C:\\Test\\Sample.xml"));
                BufferedReader bufferedReaderNewFile = new BufferedReader(new FileReader("C:\\Test\\Sample1.xml"))) {

            XMLUnit.setIgnoreWhitespace(true);
            XMLUnit.setIgnoreAttributeOrder(true);
            XMLUnit.setIgnoreComments(true);

            Diff d = new Diff(bufferedReaderExistingFile, bufferedReaderNewFile); 
            d.overrideElementQualifier(new RecursiveElementNameAndTextQualifier());
            DetailedDiff detailedDiff = new DetailedDiff(d);
            List<?> allDifferences1 = detailedDiff.getAllDifferences();

            System.out.println("  difference are :: " + allDifferences1.isEmpty());
            System.out.println("  difference are :: " + allDifferences1.size());
            System.out.println("  difference are :: " + allDifferences1.toString());

        }catch(Exception e) {
            System.out.println(e.getMessage());
        }
    }

}

我也试过下面的代码:

Diff diff = DiffBuilder.compare(bufferedReaderExistingFile)
    .withTest(bufferedReaderNewFile).ignoreComments()
    .ignoreWhitespace()
    .withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byName))
    .checkForSimilar()
    .build();

System.out.println("  difference are :: " + diff.hasDifferences());

【问题讨论】:

  • 将它们转换为Java对象并运行equals方法
  • 将两个对象放入hashmap并比较两者
  • @stultuske 这行不通。首先,你不需要在java中将任何东西转换为Object,因为所有非原始数据类型总是从Object继承,所以你总是可以调用equals方法。无论如何,只有当两个值引用同一个对象时,equals才会返回true。
  • @LluísSuñol 我没有说要转换为 Object。我也没有说这是最好的方法,它是一种选择,这就是为什么我将它作为评论发布,而不是作为答案。

标签: java xml xmlunit


【解决方案1】:

您可以使用 DifferenceEvaluators 做到这一点:

DifferenceEvaluator evaluator = DifferenceEvaluators
  .downgradeDifferencesToEquals(ComparisonType.CHILD_NODELIST_SEQUENCE);



Diff diff = DiffBuilder.compare(bufferedReaderExistingFile)
    .withTest(bufferedReaderNewFile).ignoreComments()
    .ignoreWhitespace()
    .withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byName))
    .withDifferenceEvaluator(evaluator)
    .checkForSimilar()
    .build();


【讨论】:

    【解决方案2】:

    您可以使用 Diff 中的 similar() 方法,如 documentation 中所述:

    返回比较结果。如果两个文档包含相同的元素和属性而不考虑顺序,则它们被认为是“相似的”。

    您的代码可能是这样的:

    Diff diff = XMLUnit.compareXML(bufferedReaderExistingFile, bufferedReaderNewFile);
    System.out.println("Both documents are similar: " + diff.similar());
    

    请注意XML matters 中的顺序,因此您提供的两个 XML 示例本质上是不同的 XML。

    【讨论】:

    • 设计一个元素顺序被认为没有语义意义的 XML 词汇表是完全合理的,因此尝试忽略元素顺序的比较。
    猜你喜欢
    • 2016-11-01
    • 2023-03-21
    • 1970-01-01
    • 1970-01-01
    • 2012-05-29
    • 1970-01-01
    • 1970-01-01
    • 2020-07-25
    • 2015-12-03
    相关资源
    最近更新 更多