我有一个完整的序列化对象的审计列表,我想比较它们并返回差异列表。通过'比较',我的意思是我想返回元素的文本已经改变的地方,或者已经添加了节点的地方(因此它不在Xml1中,但它在Xml2中 - 它不会发生反过来)< / p>
示例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);
}
}
}
可能我的代码尝试距离很远,并且有更好的方法可做,欢迎任何建议!
编辑添加: 我最终使用了MS Xml Diff Tool,下面的代码生成了两个xml节点的大型html表列表,其中差异以绿色突出显示。所以它可能(虽然是疯狂的)产生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();
答案 0 :(得分: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>";
Id
中的CourseBookings
值不同:
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>";
创建读者的努力方法(如果需要,请更改为XDocument
):
var node1 = XElement.Parse(xml1).CreateReader();
var node2 = XElement.Parse(xml2).CreateReader();
准备结果编写者:
var result = new XDocument();
var writer = result.CreateWriter();
做差异:
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>