2012-05-07 10 views
5

Ho una lista di controllo piena di oggetti serializzati, e mi piacerebbe confrontarli e restituire un elenco delle differenze. Con "confronto" intendo che voglio tornare dove il testo di un elemento è cambiato, o dove è stato aggiunto un nodo (quindi non è in Xml1, ma è in Xml2 - non succederà il contrario)Confronta i frammenti XML e le differenze di ritorno

XML di esempio:

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

gli spazi dei nomi ed i nomi/caso dei tag non cambierà. Tutto ciò che può cambiare in questo esempio sono i valori tra i tag e il numero di "CourseHotelLink's (è un elenco serializzato).

Il risultato finale che vorrei è un elenco di quale nodo è stato modificato, il vecchio valore e il nuovo valore.

Qual è l'opzione migliore per confrontarli? Sto usando .Net 4.0 quindi linq è un'opzione. Devo essere in grado di fare il confronto senza necessariamente conoscere i nomi di tutti i nodi, anche se confronterò solo due oggetti dello stesso tipo. Ho cercato di utilizzare il seguente codice, ma non riesco ad adattarlo per individuare le modifiche nel testo e i nodi aggiuntivi.

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

sua probabile miei tentativi di codice sono miglia al largo e c'è un modo molto migliore da fare, qualche suggerimento benvenuti!

ALLESTITO per aggiungere: Ho finito per utilizzare lo strumento MS Xml Diff, il codice seguente produce un grande elenco di tabelle html dei due nodi xml, con le differenze evidenziate in verde. Quindi è possibile (anche se folle) produrre l'html, quindi riordinarlo per trovare il testo 'lightgreen' (il valore evidenziato), quindi eseguire alcune formazioni di stringhe per visualizzare solo il nodo figlio modificato.

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(); 
+1

Date un'occhiata a questo post: http://stackoverflow.com/questions/167946/how-would-you-compare-two-xml-documents –

+0

Non ho ancora capito come ottenere MS Diff e Patch per prendere stringhe XML- il mio XML proviene da un database e non voglio dover creare file ogni volta che voglio t o usalo ... Potrebbe essere me stesso essere denso. – UglyTeapot

+0

Non è necessario creare file, viene fornito con molti sovraccarichi per confrontare i file, XmlTextReader o XmlNode –

risposta

7

L'utilizzo di XMlDiff è la strada da percorrere per dimostrare che questo è un codice funzionante. Sto usando il tuo XML. Se l'XML è diverso (o non valido), questo potrebbe non funzionare.

originale:

var xml1 = @"<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>"; 

diverso Id valore nel CourseBookings:

var xml2 = @"<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>1</Id> 
    </CourseHotelLink> 
</CourseBookings> 
</HotelBookingView>"; 

Basso modo lo sforzo di creare lettori (modifica XDocument se necessario):

var node1 = XElement.Parse(xml1).CreateReader(); 
var node2 = XElement.Parse(xml2).CreateReader(); 

Preparare il risultato scrittore:

var result = new XDocument(); 
var writer = result.CreateWriter(); 

fare il diff:

var diff = new Microsoft.XmlDiffPatch.XmlDiff();  
diff.Compare(node1, node2, writer); 
writer.Flush(); writer.Close(); 

result è ora un XDocument che contiene una sintesi delle differenze:

<xd:xmldiff version="1.0" srcDocHash="14506386314386767543" options="None" fragments="no" xmlns:xd="http://schemas.microsoft.com/xmltools/2002/xmldiff"> 
    <xd:node match="1"> 
    <xd:node match="4"> 
     <xd:node match="1"> 
     <xd:node match="1"> 
      <xd:change match="1">1</xd:change> 
     </xd:node> 
     </xd:node> 
    </xd:node> 
    </xd:node> 
</xd:xmldiff> 
+0

Questo funziona, grazie! Quindi ho solo bisogno di analizzare il diffgram per renderlo in grado di visualizzare cose come 'CourseBookings Id era 0, ora 1', che dovrebbe essere divertente! – UglyTeapot

+0

Non dimenticare di accettare se risponde alla domanda originale :-) Ci sono un sacco di informazioni su come interpretare il ritorno da 'xmldiff'. – yamen

+0

Accettato, grazie! E ... ci sono esempi su come interpretare i diffgram per mostrare solo le differenze? Il mio google-fu debole non sta trovando nulla – UglyTeapot

Problemi correlati