0

我正在尝试实现有意义的 XML 比较。我想比较两个不同的 XML 以了解它们是否“有意义”相等。

示例 XML 1:

    <?xml version="1.0" encoding="UTF-8"?>
    <al:moAttribute>
         <al:name>impiId</al:name>
         <al:value>616731935012345678</al:value>
    </al:moAttribute>

    <al:moAttribute>
          <al:name>impuId</al:name>
          <al:value>tel:+16167319350</al:value>
    </al:moAttribute> 

XML 2:

    <?xml version="1.0" encoding="UTF-8"?>
    <al:moAttribute>
          <al:name>impuId</al:name>
          <al:value>tel:+16167319350</al:value>
    </al:moAttribute>
    <al:moAttribute>
         <al:name>impiId</al:name>
         <al:value>616731935012345678</al:value>
    </al:moAttribute>

在此示例中,两个 XML 都“有意义”相同,但仅在元素顺序上有所不同。我想比较他们两个,看看他们是否几乎相等。

我试过这个解决方案:

在 Java 中比较 2 个 XML 文档的最佳方法

我试过了 :

XMLUnit.setIgnoreWhitespace(true);
diff.identical (...);
diff.similar (...);

但如果 XML 的顺序不同,则 XML 比较返回 false。

请问有什么建议吗?

4

5 回答 5

1

XML 级别的任何工具都假定元素的顺序很重要。如果您知道在您的特定词汇表中,元素的顺序并不重要,那么您需要一个能够理解您的词汇表的工具。因此,您最好的选择是编写一个规范化转换(通常在 XSLT 中),从文档中删除不相关的差异(例如,通过在某个合适的键上对元素进行排序),以便在使用标准 XML 工具(可能在 XML 之后)进行比较时,它们比较相等规范化)。

于 2015-07-18T12:35:46.937 回答
0

您可以使用 jaxb 来实现您的目标(例如http://www.mkyong.com/java/jaxb-hello-world-example/

1 使用 jaxb 从给定的两个 xml 文件构造两个 java 对象

2 在每个 java 对象中,每个 xml 文件都有一个 al:values 列表(你只关心这个)

3 比较这两个列表请参考简单的方法来查找两个不同的列表是否包含完全相同的元素?

通过这样做,您将克服订单问题

于 2015-07-18T04:22:16.560 回答
0

您可能会发现 xmlunit 的 RecursiveElementNameAndTextQualifier 在这里很有用。这是一个片段

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

Document docx1 = XMLUnit.buildDocument(..);
Document docx2 = XMLUnit.buildDocument(..);

Diff diff = new Diff(docx1, docx2);
DifferenceEngine engine = new DifferenceEngine(diff);

ElementQualifier qualifier = new RecursiveElementNameAndTextQualifier();
diff = new Diff(docx1, docx2, engine, qualifier);
diff.overrideDifferenceListener(new DifferenceListener()
{
    @Override public int differenceFound(Difference difference)
    {
         //do something with difference
         // return processDiff(difference);

    }

    @Override public void skippedComparison(Node node, Node node1)
    {
        //no op
    }
});

//check diff.identical() || diff.similar();
于 2015-07-18T04:43:43.050 回答
0

伙计们,这对我来说绝对完美。无论变化在哪里,它都显示出差异。

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.net.URL;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.custommonkey.xmlunit.DetailedDiff;
import org.custommonkey.xmlunit.Diff;
import org.custommonkey.xmlunit.Difference;
import org.custommonkey.xmlunit.XMLUnit;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;

public class Xmlreader {
     public static void main(String[] args) throws SAXException, IOException, ParserConfigurationException {
         XMLUnit.setIgnoreWhitespace(true);
         XMLUnit.setIgnoreComments(true);
         XMLUnit.setIgnoreAttributeOrder(true);
         DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
         dbf.setNamespaceAware(true);
         dbf.setCoalescing(true);
         dbf.setIgnoringElementContentWhitespace(true);
         dbf.setIgnoringComments(true);
         DocumentBuilder db = dbf.newDocumentBuilder();

     Document doc1 = db.parse(new File("C:/Users/sravanlx/Desktop/base.xml"));
     doc1.normalizeDocument();

     Document doc2 = db.parse(new File("C:/Users/sravanlx/Desktop/base2.xml"));
       /* URL url1 = Xmlreader.class.getResource("C:/Users/sravanlx/Desktop/base.xml");
        URL url2 = Xmlreader.class.getResource("C:/Users/sravanlx/Desktop/base2.xml");
        FileReader fr1 = null;
        FileReader fr2 = null;
        try {
            fr1 = new FileReader("C:/Users/username/Desktop/base.xml");
            fr2 = new FileReader("C:/Users/username/Desktop/base2.xml");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }*/

        Diff diff = new Diff(doc1, doc2);
        System.out.println("Similar? " + diff.similar());
        System.out.println("Identical? " + diff.identical());

        DetailedDiff detDiff = new DetailedDiff(diff);
        List differences = detDiff.getAllDifferences();
        for (Object object : differences) {
            Difference difference = (Difference)object;
            System.out.println("***********************");
            System.out.println(difference);
            System.out.println("***********************");
        }
    } }
于 2018-01-17T07:31:51.170 回答
0

我已经使用 XSLT 解决了这个问题,它在我的 github 中使用了无序树比较。基本上它会输出任何两个 xml 文件的匹配和不匹配,以及它相对于树根的位置。例如:

<a>
 <c/>
 <e/>
</a>

和:

<a>
 <e/>
 <c/>
</a>

会被平等对待。您只需修改工作表顶部的文件变量以选择要比较的 XML 文件。 https://github.com/sflynn1812/xslt-diff-turbo

从效率的角度来看,任何树比较算法的速度都取决于两棵树中差异的数量。

目前要将其应用于您的示例,我建议首先删除 xml 命名空间,因为目前不支持。

于 2020-04-19T13:25:04.613 回答