Porównaj fragmenty XML i różnice zwrotów
Mam listę kontroli pełną serializowanych obiektów i chciałbym je porównać i zwrócić listę różnic. Przez „porównaj” mam na myśli to, że chcę wrócić tam, gdzie zmienił się tekst elementu lub gdzie został dodany węzeł (więc nie ma go w Xml1, ale jest w Xml2 - nie stanie się inaczej)
Przykładowy 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>
Przestrzenie nazw i nazwy / wielkość znaczników nie ulegną zmianie. Wszystko, co może się zmienić w tej próbce, to wartości między znacznikami i liczba „CourseHotelLink's” (jego lista serializowana).
Ostateczny rezultat, jaki chciałbym uzyskać, to lista zmienionych węzłów - stara wartość i nowa wartość.
Jaka jest najlepsza opcja, aby je porównać? Używam .Net 4.0, więc linq jest opcją. Muszę być w stanie dokonać porównania bez konieczności znajomości nazw wszystkich węzłów - chociaż kiedykolwiek porównuję tylko dwa obiekty tego samego typu. Próbowałem użyć następującego kodu, ale nie mogę go przystosować, aby wybrać zmiany zarówno w tekście, jak iw dodatkowych węzłach.
<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>
Prawdopodobnie moje próby kodu są mile oddalone i jest o wiele lepszy sposób, wszelkie sugestie mile widziane!
EDITTED, aby dodać: Skończyło się na używaniu narzędzia MS Xml Diff, poniższy kod tworzy dużą tabelę html zawierającą dwa węzły xml, z różnicami podświetlonymi na zielono. Tak więc możliwe jest (choć szalone) wyprodukowanie html, a następnie sortowanie go w celu znalezienia tekstu „lightgreen” (podświetlona wartość), a następnie wykonanie pewnych formacji łańcuchowych w celu wyświetlenia tylko zmienionego węzła podrzędnego.
<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>