it-swarm.dev

Jak byste porovnávali dva dokumenty XML?

Jako součást základní třídy pro některé rozsáhlé testování jednotek píšu pomocnou funkci, která rekurzivně porovnává uzly jednoho objektu XmlDocument s jiným v jazyce C # (.NET). Některé požadavky:

  • První dokument je source , např. co chci, aby dokument XML vypadal. Druhá je tedy ta, kterou chci najít rozdíly a nesmí obsahovat uzly extra v prvním dokumentu.
  • Musí se jednat o výjimku, když se zjistí příliš mnoho významných rozdílů, a člověk by měl být snadno pochopen lidským pohledem na popis.
  • Pořadí prvků dítěte je důležité, atributy mohou být v libovolném pořadí.
  • Některé atributy jsou ignorovatelné; specificky xsi:schemaLocation a xmlns:xsi, i když bych chtěl být schopen projít, které z nich jsou.
  • Předpony pro jmenné prostory musí odpovídat atributům i prvkům.
  • Mezery mezi prvky jsou irelevantní.
  • Prvky budou buď mít podřízené elementy neboInnerText, ale ne obojí.

Zatímco něco spolu sešrotuji: napsal někdo takový kód a bylo by možné ho zde sdílet?

Co byste nazval prvním a druhým dokumentem? Mluvil jsem o nich jako o "zdroji" a "cíli", ale je to špatné, protože zdroj je to, co chci cíl aby vypadalo jako, jinak bych udělal výjimku.

57
Neil C. Obremski

Společnost Microsoft má rozhraní API rozhraní XML , které můžete použít

53
Danimal
6
Andrej Adamenko

try XMLUnit . Tato knihovna je dostupná pro Java i .Net

5

Srovnání XML dokumentů je komplikované. Google pro xmldiff (existuje i řešení Microsoft) pro některé nástroje. To jsem vyřešil pár způsoby. Použil jsem XSLT k třídění prvků a atributů (protože někdy by se zobrazovaly v jiném pořadí, a nezajímalo mě o to) a filtroval jsem atributy, které jsem nechtěl porovnávat, a pak jsem použil XML: : Diff nebo XML ​​:: SemanticDiff Perl modul, nebo docela vytištěný každý dokument s každým prvkem a atributem na samostatném řádku, a pomocí příkazového řádku Unix diff na výsledky.

5
runrig

Tento kód neuspokojuje všechny vaše požadavky, ale je to jednoduché a používám pro své testy. Pořadí atributů nezáleží, ale pořadí prvků má. Element vnitřní text není srovnáván. Při porovnání atributů jsem také ignoroval případ, ale můžete ho snadno odstranit.

public bool XMLCompare(XElement primary, XElement secondary)
{
    if (primary.HasAttributes) {
        if (primary.Attributes().Count() != secondary.Attributes().Count())
            return false;
        foreach (XAttribute attr in primary.Attributes()) {
            if (secondary.Attribute(attr.Name.LocalName) == null)
                return false;
            if (attr.Value.ToLower() != secondary.Attribute(attr.Name.LocalName).Value.ToLower())
                return false;
        }
    }
    if (primary.HasElements) {
        if (primary.Elements().Count() != secondary.Elements().Count())
            return false;
        for (var i = 0; i <= primary.Elements().Count() - 1; i++) {
            if (XMLCompare(primary.Elements().Skip(i).Take(1).Single(), secondary.Elements().Skip(i).Take(1).Single()) == false)
                return false;
        }
    }
    return true;
}
4
Two Cents

Dalším způsobem, jak toho dosáhnout, by bylo - 

  1. Získejte obsah obou souborů do dvou různých řetězců. 
  2. Proveďte transformaci řetězců pomocí XSLT (což zkopíruje vše do dvou nových řetězců). Tím zajistíte, že budou odstraněny všechny prostory mimo prvky. Výsledkem budou dva nové řetězce. 
  3. Teď si srovnávejte oba struny. 

To vám nedá přesné umístění rozdílu, ale pokud chcete vědět, jestli je rozdíl, je to snadné bez knihoven třetích stran.

3
Do Will

Používám ExamXML pro porovnání XML souborů. Můžete to vyzkoušet. Autoři A7Soft také poskytují API pro porovnávání XML souborů

3
Alex Gulin

https://github.com/CameronWills/FatAntelope Další alternativní knihovna k Microsoft XML Diff API. Má XML algoritmus pro provádění neuspořádaného porovnání dvou dokumentů XML a vytváří optimální shodu.

Je to C # port algoritmu X-Diff popsaný zde: http://pages.cs.wisc.edu/~yuanwang/xdiff.html

Disclaimer: Napsal jsem to :)

3
cwills

Není relevantní pro OP, protože v současné době ignoruje pořadí dětí, ale pokud chcete pouze kódové řešení, můžete vyzkoušet XmlSpecificationCompare který I poněkud nesprávně vyvinutý.

2
Eli Algranti

Napsal jsem tento XSLT 1.0 založený srovnávací list, který porovnáte b.xml se vstupním xml výstupem rozdílů položek ve vstupu, které nejsou v b.xml.

https://github.com/sflynn1812/xslt-diff

0
Stephen Flynn

Pro porovnání dvou XML výstupů v automatizovaném testování jsem našel XNode.DeepEquals.

Porovná hodnoty dvou uzlů, včetně hodnot všech sestupných uzlů.

Používání:

var xDoc1 = XDocument.Parse(xmlString1);
var xDoc2 = XDocument.Parse(xmlString2);

bool isSame = XNode.DeepEquals(xDoc1.Document, xDoc2.Document);
//Assert.IsTrue(isSame);

Odkaz: https://docs.Microsoft.com/en-us/dotnet/api/system.xml.linq.xnode.deepequals?view=netcore-2.2

0
Mirek

Na základě @ dvou centů odpověď a pomocí tohoto odkazu XMLSorting i vytvořil jsem vlastní XmlComparer 

Porovnání programu XML

private static bool compareXML(XmlNode node, XmlNode comparenode)
    {

        if (node.Value != comparenode.Value)
            return false;

            if (node.Attributes.Count>0)
            {
                foreach (XmlAttribute parentnodeattribute in node.Attributes)
                {
                    string parentattributename = parentnodeattribute.Name;
                    string parentattributevalue = parentnodeattribute.Value;
                    if (parentattributevalue != comparenode.Attributes[parentattributename].Value)
                    {
                        return false;
                    }

                }

            }

          if(node.HasChildNodes)
            {
            sortXML(comparenode);
            if (node.ChildNodes.Count != comparenode.ChildNodes.Count)
                return false;
            for(int i=0; i<node.ChildNodes.Count;i++)
                {

                string name = node.ChildNodes[i].LocalName;
                if (compareXML(node.ChildNodes[i], comparenode.ChildNodes[i]) == false)
                    return false;
                }

            }



        return true;
    }

Třídění XML programu

 private static void sortXML(XmlNode documentElement)
    {
        int i = 1;
        SortAttributes(documentElement.Attributes);
        SortElements(documentElement);
        foreach (XmlNode childNode in documentElement.ChildNodes)
        {
            sortXML(childNode);

        }
    }



  private static void SortElements(XmlNode rootNode)
    {



            for(int j = 0; j < rootNode.ChildNodes.Count; j++) {
                for (int i = 1; i < rootNode.ChildNodes.Count; i++)
                {
                    if (String.Compare(rootNode.ChildNodes[i].Name, rootNode.ChildNodes[1 - 1].Name) < 0)
                    {
                        rootNode.InsertBefore(rootNode.ChildNodes[i], rootNode.ChildNodes[i - 1]);

                    }


                }
            }
           // Console.WriteLine(j++);


    }
 private static void SortAttributes(XmlAttributeCollection attribCol)
    {
        if (attribCol == null)
            return;
        bool changed = true;
        while (changed)
        {
            changed = false;
            for (int i = 1; i < attribCol.Count; i++)
        {
                if (String.Compare(attribCol[i].Name, attribCol[i - 1].Name) < 0)
                {
                    //Replace
                    attribCol.InsertBefore(attribCol[i], attribCol[i - 1]);
                    changed = true;

                }
            }
        }
    }
0
Chetan Mehra