2012-05-07 84 views
5

我有一個充滿序列化對象的審計列表,我想比較它們並返回差異列表。通過'比較'我的意思是我想返回一個元素的文本已經改變的地方,或者添加了一個節點的地方(所以它不在Xml1中,但它在Xml2中 - 它不會以相反的方式發生)比較XML片段和返回差異

示例XML:

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

的命名空間和名稱/標籤的情況下也不會改變。本示例中所有可以改變的是標籤之間的值以及'CourseHotelLink(它的序列化列表)的數量。

我想要的最終結果是哪個節點已更改的列表 - 舊值和新值。

什麼是比較它們的最佳選擇?我使用.Net 4.0,所以linq是一個選項。我需要能夠進行比較而不必知道所有節點的名稱 - 儘管我只會比較兩個相同類型的對象。我一直在嘗試使用下面的代碼,但我無法設法使其適應於挑選文本中的更改以及額外的節點。

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

它可能是我的代碼嘗試是英里關閉,有一個更好的方法來做,歡迎任何建議!

EDITTED要添加: 我最終使用了MS Xml Diff工具,下面的代碼生成了一個大的html表格列表,其中兩個xml節點以綠色突出顯示。所以它可能(儘管是瘋狂的)生成html,然後對其進行排序以找到文本'lightgreen'(突出顯示的值),然後執行一些字符串形成以僅顯示更改後的子節點。

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

看看這篇文章:http://stackoverflow.com/questions/167946/how-will-you-compare-two-xml-documents –

+0

我還沒有弄清楚如何讓MS Diff和Patch採用XML字符串 - 我的XML來自數據庫,我不想每次我想要創建文件o使用它...可能只是我變得密集。 – UglyTeapot

+0

您不需要創建文件,它帶有許多重載比較文件,XmlTextReader或XmlNode –

回答

7

使用XMlDiff是要走的路 - 證明它是一些工作代碼。我正在使用你的XML。如果XML不同(或無效),這可能不起作用。

原文:

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

CourseBookings不同Id值:創建讀者(如果需要改變XDocument)的

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

省力的方式:

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

準備結果作者:

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

執行DIFF:

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

result現在是包含的差異彙總的XDocument

<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

這確實有用,謝謝!所以我只需要解析diffgram就可以顯示'CourseBookings Id is 0,now 1'這樣的東西,這應該很有趣! – UglyTeapot

+0

不要忘記接受它是否回答原始問題:-)關於如何解釋來自'xmldiff'的回報有很多信息。 – yamen

+0

已接受,謝謝!還有一些例子如何解釋差異只顯示差異?我的弱谷歌找不到任何東西 – UglyTeapot