检查一个XML文件是第二个XML的“子集”的最简单方法是什么?

时间:2012-06-03 16:32:38

标签: java xml xmlunit

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

我正在研究Java + XMLUnit。但是,XMLUnit没有针对此的精确解决方案。请帮忙。

感谢。

2 个答案:

答案 0 :(得分:2)

Here is a sample code from xmlunit

实际上,一种方法比较了两个XML并发现了差异。

 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进行比较(将其中一个保留为骨架XML),以查找其中一个是否是其他的子集。

如果这种方式不能令人满意,还有另一种方法可以找到给定的两个 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()); } 之间的所有差异。

{{1}}

有关详情,请参阅docs of XMLUnit

答案 1 :(得分:1)

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

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

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

  1. 这里的逻辑是我要忽略的节点,即价格。 /书店/书[价格&gt; 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++;
                }
            }
        }
    

    希望这会有所帮助。