XML比较 - 略有改动

时间:2012-06-01 09:25:31

标签: java xml xmlunit

以下是我要解决的问题。

  1. 我有两个包含XML文件的文件夹。
  2. 一个文件夹 - 比如说“source”文件夹 - 包含大约350,000个XML文件。
  3. 另一个文件夹 - 比如说“compare”文件夹 - 包含相同的350,000个XML文件和更多文件。
  4. 两者中存在的350,000个文件具有相同的名称。完全一样。
  5. 但是,“source”中的文件与“compare”中的文件略有不同。比较中的文件可能(或可能不)具有一些额外的节点。
  6. 我需要比较“来源”和“比较”中的“同名文件”。如果 - 对于“source”中的每个文件 - “source”文件中存在的所有节点都出现在“compare”文件中 - 我需要生成一个Ok报告。
  7. 如果没有,即
  8. “source”中有一些文件没有出现在“compare”
  9. 在“source”的任何文件中都有一些节点在“compare”的相应文件中不存在
  10. 然后我需要创建一个错误报告,其中包含缺失的详细信息。
  11. 我目前正在针对此问题寻求Java + XMLUnit,并且不确定是否可以解决它。即使它是,我绝对不确定这是否是最佳的工具选择。

    非常感谢任何帮助/建议。

4 个答案:

答案 0 :(得分:2)

就个人而言,我只会在整个文件夹上进行文件比较,然后当我找到具有相同名称但是校验和大小不同的文件时,请检查节点。如果文件具有相同的名称,相同的大小和相同的校验和,则无需检查文件。

答案 1 :(得分:1)

您需要按步骤继续。

  1. 列出您的350,000个文件。 “compare”文件夹中的这些额外文件与您的问题无关。
  2. 通过考虑相同的文件来缩小要比较的文件数量。您可以简单地加载它们并比较生成的字符串,因为Stirng使用哈希码进行比较。
  3. 比较两个文件夹中xml文件的实例。我认为最好的方法是使用XMLUnit。 应该是这样的:

    Diff diff = new Diff(sourceXml, compareXml); if (diff.identical()) { // whatever you want to do }

  4. 当然,如果你的文件不是太大,这种方法效果最好。

答案 2 :(得分:1)

看看DeltaXML产品;它可能比自己编写代码便宜。

答案 3 :(得分:0)

首先要做的事情。让我记录下来,说XMLUnit是一个宝石。我爱它。如果您正在查看XML值/属性/结构等的单元测试,您可能会发现使用XMLUnit的现成解决方案。 This is a good place to start from

它非常具有可扩展性。它已经带有身份检查(如在XML中具有相同顺序的相同元素和属性)或相似性检查(如在XML中具有相同的元素和属性,无论顺序如何)。

然而,就我而言,我一直在寻找略有不同的用法。我有一个很大的XML(几百个节点)和一堆XML文件(大约350,000个)。我不需要比较某些特定的节点,我可以用XPATH来识别它们。它们不一定总是在XML中处于相同的位置,但有一些通用的方法用XPATH识别它们。有时,某些节点会根据其他一些节点的值被忽略。只是提出一些想法

  1. 这里的逻辑是我要忽略的节点,即价格。 /书店/书[价格> 35] /价格

  2. 此处的逻辑位于处于相对位置的节点上。我想根据价格的价值忽略作者。而这两者是相关的。 /书店/书[价= 30] /./作者

  3. 经过多次修修补补后,我选择了低技术解决方案。在使用XMLUnit比较文件之前,我使用XPATH来屏蔽要忽略的节点的值。

        public static int massageData(File xmlFile, Set<String> xpaths, String mask)
            throws JDOMException, IOException {
        logger.debug("Data massaging started for " + xmlFile.getAbsolutePath());
        int counter = 0;
    
        Document doc = (Document) new SAXBuilder().build(xmlFile
                .getAbsolutePath());
    
        for (String xpath : xpaths) {
            logger.debug(xpath);
            XPathExpression<Element> xpathInstance = XPathFactory.instance()
                    .compile(xpath, Filters.element());
            List<Element> elements = xpathInstance.evaluate(doc);
            // element = xpathInstance.evaluateFirst(doc);
            if (elements != null) {
                if (elements.size() > 1) {
                    logger.warn("Multiple matches were found for " + xpath
                            + " in " + xmlFile.getAbsolutePath()
                            + ". This could be a *potential* error.");
                }
                for (Element element : elements) {
                    logger.debug(element.getText());
                    element.setText(mask);
                    counter++;
                }
            }
        }
    

    希望这会有所帮助。