Сравнить фрагменты XML и вернуть различия
У меня есть список аудита, полный сериализованных объектов, и я хотел бы сравнить их и вернуть список различий. «Сравнить» Я имею в виду, что я хочу вернуть, где текст для элемента изменился или где был добавлен узел (поэтому его нет в Xml1, но в Xml2 - это не произойдет наоборот)
Образец 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>
Пространства имен и имена / регистр тегов не изменятся. Все, что может измениться в этом примере, это значения между тегами и количество «CourseHotelLink» (его сериализованный список).
Конечный результат, который мне нужен, это список того, какой узел изменился - старое значение и новое значение.
Каков наилучший вариант для сравнения? Я использую .Net 4.0, поэтому вариант linq. Мне нужно уметь сравнивать, не зная имена всех узлов, хотя я буду сравнивать только два объекта одного типа. Я пытался использовать следующий код, но мне не удается адаптировать его для выбора изменений в тексте, а также дополнительных узлов.
<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>
Скорее всего, мои попытки написания кода находятся далеко, и есть гораздо лучший способ сделать это, любые предложения приветствуются!
РЕДАКТИРОВАТЬ добавить: В итоге я использовал MS Xml Diff Tool, следующий код выдает большой список HTML-таблиц двух узлов xml, различия в которых выделены зеленым цветом. Таким образом, можно (хотя и безумно) создать html, а затем отсортировать его, чтобы найти текст «lightgreen». (выделенное значение), затем выполните некоторые строковые формирования, чтобы отобразить только измененный дочерний узел.
<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>