Vergleichen Sie XML-Fragmente und geben Sie Unterschiede zurück

Ich habe eine Prüfliste mit serialisierten Objekten und möchte diese vergleichen und eine Liste der Unterschiede zurückgeben. Mit "Vergleichen" meine ich, dass ich zurückgeben möchte, wo sich der Text für ein Element geändert hat oder wo ein Knoten hinzugefügt wurde (also nicht in Xml1, sondern in Xml2 - es wird nicht umgekehrt passieren).

Beispiel-XML:

<code><HotelBookingView xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Id>119</Id>
  <RoomId>1</RoomId>
  <ChangeRequested>false</ChangeRequested>
  <CourseBookings>      
    <CourseHotelLink>
      <Id>0</Id>
    </CourseHotelLink>
</CourseBookings>
</HotelBookingView>
</code>

Die Namespaces und die Namen / Groß- / Kleinschreibung der Tags ändern sich nicht. In diesem Beispiel können sich nur die Werte zwischen den Tags und die Anzahl der CourseHotelLinks (eine serialisierte Liste) ändern.

Das Endergebnis, das ich möchte, ist eine Liste, welcher Knoten sich geändert hat - der alte Wert und der neue Wert.

Was ist die beste Option, um sie zu vergleichen? Ich verwende .Net 4.0, daher ist Linq eine Option. Ich muss in der Lage sein, den Vergleich durchzuführen, ohne unbedingt die Namen aller Knoten zu kennen - obwohl ich immer nur zwei Objekte desselben Typs vergleichen werde. Ich habe versucht, den folgenden Code zu verwenden, kann ihn jedoch nicht anpassen, um Änderungen im Text sowie zusätzliche Knoten zu erkennen.

<code>XmlDocument Xml1 = new XmlDocument();
XmlDocument Xml2 = new XmlDocument();
Xml1.LoadXml(list[1].Changes);
Xml2.LoadXml(list[2].Changes);
foreach (XmlNode chNode in Xml2.ChildNodes)
{
   CompareLower(chNode);
}

protected void CompareLower(XmlNode aNode)
{
    foreach (XmlNode chlNode in aNode.ChildNodes)
    {
        string Path = CreatePath(chlNode);
        if (chlNode.Name == "#text")
        {
            //all my efforts at comparing text have failed
            continue;
        }
        if (Xml1.SelectNodes(Path).Count == 0)
        {
            XmlNode TempNode = Xml1.ImportNode(chlNode, true);
            //node didn't used to exist, this works- though doesn't return values
            str = str + "New Node: " + TempNode.Name + ": " + TempNode.Value;
        }
        else
        {
            CompareLower(chlNode);
        }
    } 
}
</code>

Es ist wahrscheinlich, dass meine Codeversuche meilenweit entfernt sind, und es gibt einen viel besseren Weg, Vorschläge willkommen zu heißen!

BEARBEITET, um hinzuzufügen: Ich habe das MS Xml Diff Tool verwendet. Der folgende Code erstellt eine große HTML-Tabellenauflistung der beiden XML-Knoten, wobei die Unterschiede grün hervorgehoben sind. Es ist also möglich (obwohl verrückt), das HTML zu produzieren, es dann zu sortieren, um den Text 'hellgrün' (den hervorgehobenen Wert) zu finden, und dann einige Zeichenketten-Formationen durchzuführen, um nur den geänderten Kindknoten anzuzeigen.

<code>var node1 = XElement.Parse("Xml string 1 here").CreateReader();
var node2 = XElement.Parse("Xml string 2 here").CreateReader();

MemoryStream diffgram = new MemoryStream();
XmlTextWriter diffgramWriter = new XmlTextWriter(new StreamWriter(diffgram));

XmlDiff xmlDiff = new XmlDiff(XmlDiffOptions.IgnoreChildOrder);
xmlDiff.Algorithm = XmlDiffAlgorithm.Fast;
xmlDiff.Compare(node1, node2,diffgramWriter);

diffgram.Seek(0, SeekOrigin.Begin);
XmlDiffView xmlDiffView = new Microsoft.XmlDiffPatch.XmlDiffView();
StringBuilder sb = new StringBuilder();
TextWriter resultHtml = new StringWriter(sb);
xmlDiffView.Load("Xml string 1", new XmlTextReader(diffgram)); 

xmlDiffView.GetHtml(resultHtml);
resultHtml.Close();
</code>

Antworten auf die Frage(1)

Ihre Antwort auf die Frage