xml-unit正确的元素限定符

时间:2016-10-26 12:51:11

标签: java xml xmlunit

这个问题是关注我的问题limitations of xml unit。 我想知道最好的元素限定符。

现在我已经创建了两个示例XML。不幸的是,我不能发布真实的。附加的没有任何意义,但它们足以表明我的问题。

在这种情况下,如果“metainfo”节点在两种情况下都相同,我希望找到两辆相似的汽车。在看了一下输出之后,我想,车库中的第一辆车与混合车间的第一辆车进行了对比。 我想,RecursiveElementNameAndTextQualifier应该识别正确的一个。

后来(再次没有意义,只是一个例子)会有一些客户看起来像:

<customer>
<age></age>
<gender></gender>
<db_info>
    <id></id>
    <…></…>
</customer>

并且如果id相同则应该相同。

carshop.xml

 <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<delivery>
<cars>
    <car>
        <number>g:ki:1675</number>
        <manufactor>npqhtgmmfh</manufactor>
        <age>2</age>
        <localcar_id>6213</localcar_id>
        <metainfo>
            <keynumber>424</keynumber>
            <colour>1</colour>
        </metainfo>
    </car>
    <car>
        <number>b:ra:5287</number>
        <manufactor>tjmeugqcar</manufactor>
        <localcar_id>625</localcar_id>
        <metainfo>
            <keynumber>3238</keynumber>
            <colour>3</colour>
        </metainfo>
    </car>
    <car>
        <number>v:eu:5387</number>
        <localcar_id>4910</localcar_id>
        <metainfo>
            <keynumber>618</keynumber>
            <colour>6</colour>
        </metainfo>
    </car>
    <car>
        <number>f:fu:8242</number>
        <manufactor>ckpoaskabi</manufactor>
        <age>9</age>
        <localcar_id>8044</localcar_id>
        <metainfo>
            <keynumber>9865</keynumber>
            <colour>6</colour>
        </metainfo>
    </car>
</cars>
</delivery>

mixedcarshop

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<delivery>
<cars>
    <car>
        <number>f:fu:8242</number>
        <manufactor>ckpoaskabi</manufactor>
        <age>9</age>
        <localcar_id>8044</localcar_id>
        <metainfo>
            <keynumber>3238</keynumber>
            <colour>3</colour>
        </metainfo>
    </car>
    <car>
        <number>b:ra:5287</number>
        <manufactor>tjmeugqcar</manufactor>
        <localcar_id>625</localcar_id>
        <metainfo>
            <keynumber>9865</keynumber>
            <colour>6</colour>
        </metainfo>
    </car>
    <car>
        <number>v:eu:5387</number>
        <localcar_id>4910</localcar_id>
        <metainfo>
            <keynumber>424</keynumber>
            <colour>1</colour>
        </metainfo>
    </car>
    <car>
        <number>g:ki:1675</number>
        <manufactor>npqhtgmmfh</manufactor>
        <age>2</age>
        <localcar_id>6213</localcar_id>
        <metainfo>
            <keynumber>618</keynumber>
            <colour>6</colour>
        </metainfo>
    </car>
</cars>
</delivery>

JAVA代码:

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.custommonkey.xmlunit.DetailedDiff;
import org.custommonkey.xmlunit.Diff;
import org.custommonkey.xmlunit.Difference;
import org.custommonkey.xmlunit.XMLUnit;
import org.custommonkey.xmlunit.examples.RecursiveElementNameAndTextQualifier;



 public class Arbeiter {

private File quelle, vergleich; 

public Arbeiter(File quelle, File vergleich) {
    this.quelle=quelle; 
    this.vergleich=vergleich;
}

public void vergleichen()
{
    long tbevore = System.currentTimeMillis();
    XMLUnit.setIgnoreAttributeOrder(Boolean.TRUE);
    XMLUnit.setIgnoreWhitespace(Boolean.TRUE);
    String f1 = lesen(quelle);
    String f2 = lesen(vergleich);

    try {
        Diff diff = new Diff(f1, f2);
        diff.overrideElementQualifier(new RecursiveElementNameAndTextQualifier());
        List<String>liste = new ArrayList<String>();
        liste.add("number");
        liste.add("manufactor");
        liste.add("age");
        liste.add("localcar_id");
        //diff.overrideDifferenceListener(new IgnoreNamedElementsDifferenceListener(findSVSW_ID(quelle)));
        diff.overrideDifferenceListener(new IgnoreNamedElementsDifferenceListener(liste));
        DetailedDiff dd = new DetailedDiff(diff);
        boolean result = dd.similar();

        StringBuilder sb = new StringBuilder(); 

        sb.append("Die Dateien "+quelle.getName() +" und "+vergleich.getName()+" wurden miteinander verglichen \n \n");
        if (result ==true)
        {
            sb.append("Die Dateien sind inhaltsgleich \n");
        }
        else
        {
            sb.append("Die Dateien unterscheiden sich \n \n");
            List<Difference>list = dd.getAllDifferences();
            for (Difference aktuell : list)
            {
                if (!aktuell.isRecoverable())
                {
                    sb.append("Der Ausdruck "+aktuell.getControlNodeDetail().getValue()+" wurde gesucht \n");
                    sb.append("Der Ausdruck "+aktuell.getTestNodeDetail().getValue()+" wurde gefunden \n");
                    sb.append("Xpath: "+aktuell.getTestNodeDetail().getXpathLocation()+"\n \n");

                }
            }
        }
        long tafter = System.currentTimeMillis();
        String dauer = Long.toString((tafter-tbevore)/1000);
        sb.append("Die Bearbeitung dauerte " +dauer+" Sekunden \n");
        speichern(sb.toString());
        System.out.println("Bearbeitung abgeschlossen. Die Ausgabedatei wurde unter " +quelle.getParent()+"/ausgabe.txt abgelegt");

    }
    catch (Exception e)
    {
        e.printStackTrace();
    }




}

private String lesen(File datei)
{
    String result ="";
    try {
        BufferedReader leser = new BufferedReader(new FileReader(datei));
        StringBuilder sb = new StringBuilder();
        String gelesen = leser.readLine();
        while (gelesen!=null)
        {
            sb.append(gelesen);
            gelesen=leser.readLine();
        }
        result=sb.toString();
        leser.close();
    } catch (FileNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    return result;
}

private List<String> findSVSW_ID(File datei)
{
    List<String>liste = new ArrayList<String>();
    liste.add("AUFTRAGSCHLUESSEL");
    liste.add("LIEFERUNGSCHLUESSEL");
    try {
        BufferedReader leser = new BufferedReader(new FileReader(datei));
        String gelesen = leser.readLine();
        while (gelesen!=null)
        {
            if (gelesen.contains("SVSW_ID"))
            {
                String [] teile = gelesen.split(">");
                String temp = teile[0].replaceAll("<", "");
                if (!liste.contains(temp))
                {
                    String t2=temp.replaceAll(" ", "");
                    liste.add(t2);
                }

            }
            gelesen=leser.readLine();
        }


    } catch (FileNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }


    return liste;
}

private void speichern(String text)
{
    File datei = new File(quelle.getParent()+"/ausgabe.txt");
    try {
        BufferedWriter schreiber = new BufferedWriter(new FileWriter(datei));
        schreiber.write(text);
        schreiber.flush();
        schreiber.close();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

}

感谢您的帮助

1 个答案:

答案 0 :(得分:0)

RecursiveElementNameAndTextQualifier是引用最多的ElementQualifier之一,但它几乎不是您需要的那个。如果它们的名称匹配并且所有子项的名称(按正确顺序)匹配并且所有子项的嵌套文本(按正确顺序)匹配,则它匹配两个元素。它不仅限于metainfo孩子,而是使用所有孩子的嵌套文本。

在给定节点的子元素上调用

ElementQualifier,您需要让它选择足够接近文档根的“正确”选项。在您比较car元素的情况下。对于那些需要ElementQualifier的人,如果metainfo/keynumber子项的嵌套文本匹配,则会接受两个可比较的元素。

没有内置的ElementQualifer足够有选择性,你必须自己写。更糟糕的是,这个自定义ElementQualifier不适用于任何其他元素(它们没有metainf/keynumber子元素),但仍然必须使用单个ElementQualifier作为整体文献。这意味着您的自定义实现将变得更加复杂。

在XMLUnit 2.x中有一个不同的解决方案,因为你可以编写ElementSelector s(大约相当于1.x中的ElementQualifier)并且有一个条件生成器。像

这样的东西
ElementSelectors.conditionalBuilder()
  .whenElementIsNamed("car").thenUse(ElementSelectors.byXPath("./metainfo/keynumber", ElementSelectors.byNameAndText))
  .elseUse(ElementSelectors.byName)
  .build();

可能会奏效。