Mam listę kontroli pełną serializowanych obiektów i chciałbym je porównać i zwrócić listę różnic. Przez "porównać" mam na myśli to, że chcę powrócić tam, gdzie zmienił się tekst elementu, lub gdzie został dodany węzeł (więc nie jest w Xml1, ale jest w Xml2 - nie stanie się odwrotnie)Porównywanie fragmentów XML i różnic zwracanych
xmlPróbka:
<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>
przestrzeni nazw i nazwy/przypadek znaczniki nie ulegnie zmianie. Wszystko, co można zmienić w tym przykładzie, to wartości między tagami i liczba "CourseHotelLink" (lista zserializowana).
Końcowy wynik, który chciałbym, to lista węzłów uległa zmianie - stara wartość i nowa wartość.
Jaki jest najlepszy sposób ich porównania? Używam .Net 4.0, więc linq jest opcją. Muszę umieć dokonać porównania bez znajomości nazw wszystkich węzłów - choć porównuję tylko dwa obiekty tego samego typu. Próbowałem użyć następującego kodu, ale nie mogę go dostosować, aby wykryć zmiany w tekście, a także dodatkowe węzły.
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);
}
}
}
Jest prawdopodobne, moje próby kodu są mile off i jest znacznie lepszy sposób to zrobić, wszelkie sugestie mile widziane!
EDITTED, aby dodać: Skończyło się na użyciu narzędzia MS Xml Diff, poniższy kod tworzy dużą tabelę html z dwoma węzłami xml, z różnicami zaznaczonymi na zielono. Więc jest to możliwe (choć szalone) do wytworzenia html, a następnie posortuj go, aby znaleźć tekst "lightgreen" (podświetlona wartość), następnie wykonaj kilka formacji smyczkowych, aby wyświetlić tylko zmieniony węzeł-dziecko.
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();
spojrzeć na tym stanowisku: http://stackoverflow.com/questions/167946/how-would-you-compare-dwa-xml-dokumenty –
Jeszcze nie opracowałem, jak uzyskać MS Diff i Patch do pobierania łańcuchów XML - mój XML pochodzi z bazy danych i nie chcę aby tworzyć pliki za każdym razem, gdy chcę o użyj go ... Może po prostu być gęsty. – UglyTeapot
Nie trzeba tworzyć plików, występuje wiele przeciążeń w celu porównania plików, XmlTextReader lub XmlNode –