【问题标题】:What is the easiest way to check that one XML file is a "subset" of the second XML?检查一个 XML 文件是否是第二个 XML 的“子集”的最简单方法是什么?
【发布时间】:2012-06-03 16:32:38
【问题描述】:

我有两个 XML 文件。第一个 XML 有一堆节点,这些节点也应该出现在第二个 XML 中。第二个 XML 也可能有一些额外的节点。我需要一个可以自动执行此检查的基于 Java 的程序 - 即它应该告诉我给定两个 XML 文件,第一个文件的所有节点都存在于第二个 xml 中。

我正在研究 Java + XMLUnit。然而,XMLUnit 对此没有确切的解决方案。请帮忙。

谢谢。

【问题讨论】:

  • 恐怕不行。我相信该链接试图实现的是比较两个预期相等的 XML。我试图断言一个 XML 是另一个 XML 的子集。稍微不一样。但事实证明这是一个很难破解的。
  • 好吧,this 对那个问题的回答说,使用那个特定的库,您可以将您的 xmls 转换为字符串,然后使用字符串操作,您可以轻松地确定一个是否是另一个的子集。跨度>
  • 这两个 XML 每次都完全不同吗?还是它们是通用模式的实例?如果您是第二种情况,您可以创建一个 xsd 并使用它来验证文件。
  • @KazekageGaara - 我明白误解在哪里了。在我的例子中,第二个 xml 可以有新节点,这些新节点可能散布在第一个 XML 中的原始节点集中。所以,字符串方法是行不通的。如果我遗漏了什么,请告诉我。

标签: java xml xmlunit


【解决方案1】:

Here is a sample code from xmlunit.

其中的一种方法实际上是比较两个XMLs 并找出差异。

 public void testCompareToSkeletonXML() throws Exception {
        String myControlXML = "<location><street-address>22 any street</street-address><postcode>XY00 99Z</postcode></location>";
        String myTestXML = "<location><street-address>20 east cheap</street-address><postcode>EC3M 1EB</postcode></location>";
        DifferenceListener myDifferenceListener = new IgnoreTextAndAttributeValuesDifferenceListener();
        Diff myDiff = new Diff(myControlXML, myTestXML);
        myDiff.overrideDifferenceListener(myDifferenceListener);
        assertTrue("test XML matches control skeleton XML " + myDiff, myDiff.similar());
    }

您可以将一个XML 与另一个进行比较(将一个保留为骨架XML),以确定一个是否是另一个的子集。

如果这种方法不令人满意,还有另一种方法可以找出给定两个XMLs 之间的所有差异。

 public void testAllDifferences() throws Exception {
        String myControlXML = "<news><item id=\"1\">War</item>"
            + "<item id=\"2\">Plague</item><item id=\"3\">Famine</item></news>";
        String myTestXML = "<news><item id=\"1\">Peace</item>"
            + "<item id=\"2\">Health</item><item id=\"3\">Plenty</item></news>";
        DetailedDiff myDiff = new DetailedDiff(compareXML(myControlXML, myTestXML));
        List allDifferences = myDiff.getAllDifferences();
        assertEquals(myDiff.toString(), 0, allDifferences.size());
    }

请参阅docs of XMLUnit 了解更多信息。

【讨论】:

    【解决方案2】:

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

    它是相当可扩展的。它已经带有身份检查(如在 XML 中具有相同的元素和属性以相同的顺序)或相似性检查(如在 XML 中具有相同的元素和属性而不管顺序)。

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

    1. 这里的逻辑是在我想忽略的节点上,即价格。 /bookstore/book[price>35]/price

    2. 这里的逻辑是在一个相对位置的节点上。我想根据价格的价值忽略作者。这两者是按位置相关的。 /bookstore/book[price=30]/./author

    经过多次修补,我决定采用低技术解决方案。在使用 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++;
                }
            }
        }
    

    希望这会有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-07-28
      • 1970-01-01
      • 1970-01-01
      • 2010-09-22
      • 1970-01-01
      • 2010-11-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多