比较XML片段放;返回差异 [英] Compare XML fragments & return differences

查看:152
本文介绍了比较XML片段放;返回差异的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个审计表满序列化对象,我想对它们进行比较,并返回的差异列表。由比较我的意思是我想回到那里为元素的文本发生了变化,或者一个节点已经被添加(所以它不是在XML1,但它是在Xml2-不会发生周围的其他方式)



示例XML:

 < HotelBookingView的xmlns:XSI =HTTP ://www.w3.org/2001/XMLSchema-instance的xmlns:XSD =http://www.w3.org/2001/XMLSchema> 
< ID和GT; 119 LT; / ID>
< RoomId> 1 LT; / RoomId>
< ChangeRequested>假LT; / ChangeRequested>
< CourseBookings>
< CourseHotelLink>
< ID和GT; 0℃; / ID>
< / CourseHotelLink>
< / CourseBookings>
< / HotelBookingView>



的命名空间和名称/标签的情况下,也不会改变。所有这一切可以在这个示例中更改标记之间的值,以及CourseHotelLink的(它的一个序列化的列表)的数量。



最终的结果,我想是的哪个节点具有更改─旧值和新值列表。



什么是比较它们的最佳选择?我使用.NET 4.0所以LINQ是一种选择。我需要能够做比较,而不必知道所有的节点 - 的名字,虽然我将只比较同类型的两个对象。我一直在尝试使用下面的代码,但我不能设法适应它挑选出文本的变化以及额外的节点。

  XmlDocument的XML1 =新的XmlDocument(); 
XmlDocument的XML2 =新的XmlDocument();
Xml1.LoadXml(名单[1]的.changes);
Xml2.LoadXml(名单[2]的.changes);
的foreach(XmlNode的chNode在Xml2.ChildNodes)
{
CompareLower(chNode);
}

保护无效CompareLower(XmlNode的阳极)
{
的foreach(XmlNode的在aNode.ChildNodes chlNode)
{
路径字符串= CreatePath(chlNode);
如果(chlNode.Name ==#text)
{
//我在比较文本的所有努力都失败
继续;
}
如果(Xml1.SelectNodes(路径).Count之间的== 0)
{
XmlNode的TempNode = Xml1.ImportNode(chlNode,真);
//节点没有用来存在,则该工程─虽然不返回值
海峡= STR +新节点:+ TempNode.Name +:+ TempNode.Value;
}
,否则
{
CompareLower(chlNode);
}
}
}



它可能我的代码企图是英里,有一个更好的方法做,有什么建​​议欢迎



EDITTED补充:!
我结束了使用MS的Xml比较工具时,下面的代码生成两个XML节点的一大HTML表列表,并以绿色突出的差异。因此,它可能(虽然疯狂)来生成HTML,然后进行排序,通过它来查找文本浅绿(高亮显示的值),然后做一些字符串编队只显示更改的子节点。

  VAR节点1 = XElement.Parse(XML字符串1这里)CreateReader()。 
VAR节点2 = XElement.Parse(XML字符串2这里)CreateReader()。

的MemoryStream的DiffGram =新的MemoryStream();
XmlTextWriter的diffgramWriter =新的XmlTextWriter(新的StreamWriter(DiffGram格式));

的xmldiff的xmldiff =新的xmldiff(XmlDiffOptions.IgnoreChildOrder);
xmlDiff.Algorithm = XmlDiffAlgorithm.Fast;
xmlDiff.Compare(节点1,节点,diffgramWriter);

diffgram.Seek(0,SeekOrigin.Begin);
XmlDiffView xmlDiffView =新Microsoft.XmlDiffPatch.XmlDiffView();
StringBuilder的SB =新的StringBuilder();
的TextWriter resultHtml =新的StringWriter(某人);
xmlDiffView.Load(XML字符串1,新的XmlTextReader(DiffGram格式));

xmlDiffView.GetHtml(resultHtml);
resultHtml.Close();


解决方案

使用的xmldiff是要走的路 - 来证明这一点这里的一些工作的代码。我使用的XML。如果XML是不同的(或无效),这可能无法正常工作。



原文:

  VAR XML1 = @< HotelBookingView的xmlns:XSI =http://www.w3.org/2001/XMLSchema-instance的xmlns:XSD =HTTP://www.w3 .ORG / 2001 / XML模式> 
<标识> 119< / ID>
< RoomId> 1< / RoomId>
< ChangeRequested>假< / ChangeRequested>
< CourseBookings>
< CourseHotelLink>
<标识> 0℃; / ID>
< / CourseHotelLink>
< / CourseBookings>
&所述; / HotelBookingView>中;



不同的编号在<$ C $价值C> CourseBookings :

  VAR XML2 = @< HotelBookingView的xmlns:XSI =HTTP ://www.w3.org/2001/XMLSchema-instance的xmlns:XSD =http://www.w3.org/2001/XMLSchema> 
< ID和GT; 119 LT; / ID>
< RoomId> 1< / RoomId>
< ChangeRequested>假< / ChangeRequested>
< CourseBookings>
< CourseHotelLink>
< ID> 1< / ID>
< / CourseHotelLink>
< / CourseBookings>
< / HotelBookingView>中;



创建读者(改为的XDocument 如果需要的话):

  VAR节点1 = XElement.Parse(XML1).CreateReader(); 
VAR节点2 = XElement.Parse(XML2).CreateReader();



准备的结果作家:

  VAR的结果=新的XDocument(); 
VAR作家= result.CreateWriter();



执行差异:

  VAR差异=新Microsoft.XmlDiffPatch.XmlDiff(); 
diff.Compare(节点1,节点,作家);
writer.Flush(); writer.Close();



结果现在是一个的XDocument 包含的差异摘要:

 < XD:的xmldiff版本= 1.0srcDocHash =14506386314386767543选项=无碎片=无的xmlns:XD =http://schemas.microsoft.com/xmltools/2002/xmldiff> 
< XD:节点匹配=1>
< XD:节点匹配=4>
< XD:节点匹配=1>
< XD:节点匹配=1>
< XD:改变比赛=1> 1 LT; / XD:变化>
< / XD:节点>
< / XD:节点>
< / XD:节点>
< / XD:节点>
< / XD:&的xmldiff GT;


I have an audit list full of serialized objects, and I'd like to compare them and return a list of the differences. By 'compare' I mean I want to return where the text for an element has changed, or where a node has been added (so its not in Xml1, but it is in Xml2- it won't happen the other way around)

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

The namespaces and the names/case of the tags will not change. All that can change in this sample is the values between the tags, and the number of 'CourseHotelLink's (its a serialized list).

The final result I would like is a list of which node has changed- the old value and the new value.

What is the best option to compare them? I am using .Net 4.0 so linq is an option. I need to be able to do the comparison without necessarily knowing the names of all the nodes- though I will only ever compare two objects of the same type. I have been trying to use the following code, but I can't manage to adapt it to pick out changes in text as well as extra nodes.

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

Its likely my code attempts are miles off and there is a much better way to do, any suggestions welcome!

EDITTED to add: I ended up using the MS Xml Diff Tool, the following code produces a big html table listing of the two xml nodes, with the differences highlighted in green. So its possible (though insane) to produce the html, then sort through it to find the text 'lightgreen' (the highlighted value), then do some string formations to display only the changed child-node.

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

解决方案

Using XMlDiff is the way to go - to prove it here's some working code. I'm using your XML. If the XML is different (or invalid), this may not work.

Original:

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

Different Id value in 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>";

Low effort way of creating readers (change to XDocument if needed):

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

Prepare the result writer:

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

Do the diff:

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

result is now an XDocument that contains a summary of the differences:

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

这篇关于比较XML片段放;返回差异的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆