Tengo una lista de auditoría llena de objetos serializados, y me gustaría compararlos y devolver una lista de las diferencias. Con 'comparar' quiero decir que quiero regresar donde ha cambiado el texto de un elemento, o donde se ha agregado un nodo (por lo tanto, no está en Xml1, pero está en Xml2, no ocurrirá al revés)Comparación de fragmentos XML y diferencias de resultado
xmlmuestra:
<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>
los espacios de nombres y los nombres/caso de las etiquetas no va a cambiar. Todo lo que puede cambiar en esta muestra son los valores entre las etiquetas y el número de 'CourseHotelLink's (es una lista serializada).
El resultado final que me gustaría es una lista de qué nodo ha cambiado: el valor anterior y el nuevo.
¿Cuál es la mejor opción para compararlos? Estoy usando .Net 4.0 así que linq es una opción. Necesito poder hacer la comparación sin conocer necesariamente los nombres de todos los nodos, aunque solo compararé dos objetos del mismo tipo. He estado tratando de usar el siguiente código, pero no puedo adaptarlo para seleccionar cambios en el texto y nodos adicionales.
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);
}
}
}
su probable mis intentos de código son millas de distancia y hay una mejor manera de hacerlo, todas las sugerencias son bienvenidas!
EDITADO para agregar: Terminé usando la herramienta MS Xml Diff Tool, el siguiente código produce una gran tabla html que enumera los dos nodos xml, con las diferencias resaltadas en verde. Entonces es posible (aunque loco) producir el html, luego ordenarlo para encontrar el texto 'lightgreen' (el valor resaltado), luego hacer algunas formaciones de cadena para mostrar solo el nodo hijo modificado.
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();
Tome un vistazo a este post: http://stackoverflow.com/questions/167946/how-you-you-compare-two-xml-documents –
Aún no he descubierto cómo obtener MS Diff y Patch para tomar cadenas XML: mi XML proviene de una base de datos y no quiero tener que crear archivos cada vez que quiero t o usarlo ... Podría ser que yo sea denso. – UglyTeapot
No necesita crear archivos, viene con muchas sobrecargas para comparar archivos, XmlTextReader o XmlNode –