Question

En tant que partie de la classe de base pour certains tests unitaires approfondis, j'écris une fonction d'assistance qui compare de manière récursive les nœuds d'un objet XmlDocument à un autre en C # (.NET). Certaines exigences de ceci:

  • Le premier document est la source , par exemple. ce que je veux que le document XML ressemble. Ainsi, le second est celui dans lequel je veux trouver des différences et ne doit pas contenir de nœuds extra qui ne figurent pas dans le premier document.
  • Doit renvoyer une exception lorsque trop de différences significatives sont trouvées et doit être facilement comprise par un simple regard humain sur la description.
  • L'ordre des éléments enfants est important, les attributs peuvent être dans n'importe quel ordre.
  • Certains attributs sont ignorables. spécifiquement xsi: schemaLocation et xmlns: xsi , bien que j'aimerais pouvoir indiquer lesquels sont.
  • Les préfixes des espaces de nom doivent correspondre dans les attributs et les éléments.
  • Les espaces entre les éléments ne sont pas pertinents.
  • Les éléments auront des éléments enfants ou InnerText , mais pas les deux.

Pendant que je regroupe quelque chose: quelqu'un a-t-il écrit un tel code et serait-il possible de le partager ici?

D'un côté, comment appelleriez-vous les premier et deuxième documents? Je me suis référé à eux comme "source" et "cible", mais cela semble anormal puisque la source est ce que je veux que la cible ressemble à, sinon je jette une exception.

Était-ce utile?

La solution

Microsoft dispose d'une API de différences XML que vous pouvez utiliser

Autres conseils

essayez XMLUnit . Cette bibliothèque est disponible pour Java et .Net

La comparaison de documents XML est compliquée. Google pour xmldiff (il existe même une solution Microsoft) pour certains outils. J'ai résolu ce problème de deux manières. J'ai utilisé XSLT pour trier les éléments et les attributs (car ils apparaissaient parfois dans un ordre différent, ce qui m'était égal), et filtrer les attributs que je ne voulais pas comparer, puis utiliser le XML :: Diff ou XML :: SemanticDiff , ou bien imprimé chaque document avec chaque élément et attribut sur une ligne distincte, et utiliser diff de ligne de commande Unix sur les résultats.

Ce code ne satisfait pas toutes vos exigences, mais il est simple et je l’utilise pour mes tests unitaires. L'ordre des attributs n'a pas d'importance, mais l'ordre des éléments l'est aussi. Le texte interne de l'élément n'est pas comparé. J'ai également ignoré le cas lors de la comparaison des attributs, mais vous pouvez facilement le supprimer.

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;
}

J'utilise ExamXML pour comparer des fichiers XML. Tu peux l'essayer. Les auteurs, A7Soft, fournissent également une API permettant de comparer des fichiers XML

https://github.com/CameronWills/FatAntelope Une autre bibliothèque alternative à l'API Microsoft XML Diff. Il dispose d'un algorithme de diff XML pour effectuer une comparaison non ordonnée de deux documents XML et produire une correspondance optimale.

C'est un port C # de l'algorithme X-Diff décrit ici: http://pages.cs.wisc.edu/~yuanwang/xdiff.html

Clause de non-responsabilité : je l'ai écrit:)

Une autre façon de le faire serait -

  1. Obtenez le contenu des deux fichiers en deux chaînes différentes.
  2. Transformez les chaînes en utilisant un XSLT (qui ne fera que copier le tout dans deux nouvelles chaînes). Cela garantira que tous les espaces en dehors des éléments sont supprimés. Cela entraînera deux nouvelles chaînes.
  3. Maintenant, comparez les deux chaînes l'une avec l'autre.

Cela ne vous donnera pas l'emplacement exact de la différence, mais si vous voulez simplement savoir s'il y a une différence, il est facile de le faire sans aucune bibliothèque tierce.

Non pertinent pour l'OP puisqu'il ignore actuellement l'ordre des enfants, mais si vous souhaitez une solution avec code uniquement, vous pouvez essayer XmlSpecificationCompare que je de manière quelque peu erronée développé.

Pour comparer deux sorties XML lors de tests automatisés, j'ai trouvé XNode.DeepEquals .

  

Compare les valeurs de deux nœuds, y compris celles de tous les nœuds descendants.

Utilisation:

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

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

Référence: https://docs.microsoft.com/en-us/dotnet/api/system.xml.linq.xnode.deepequals?view=netcore-2.2

La réponse de @Two Cents est basée sur ce lien et XMLSorting . i ont créé mon propre XmlComparer

Comparez le programme 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;
    }

Trier les programmes XML

 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;

                }
            }
        }
    }

J'ai écrit cette feuille de comparaison basée sur XSLT 1.0 que vous comparez b.xml à l'entrée XML qui affiche les différences d'éléments de l'entrée qui ne figurent pas dans b.xml.

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

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top