9

シリアル化されたオブジェクトでいっぱいの監査リストがあります。それらを比較して、違いのリストを返したいと思います。「比較」とは、要素のテキストが変更された場所、またはノードが追加された場所を返したいことを意味します(つまり、Xml1にはありませんが、Xml2にはあります)。

サンプル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」(シリアル化されたリスト)の数だけです。

私が望む最終結果は、変更されたノードのリストです-古い値と新しい値。

それらを比較するための最良のオプションは何ですか?私は.Net4.0を使用しているので、linqはオプションです。同じタイプの2つのオブジェクトのみを比較しますが、必ずしもすべてのノードの名前を知らなくても比較できる必要があります。私は次のコードを使用しようとしていますが、テキストの変更や余分なノードを選択するようにそれを適応させることができません。

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を使用することになりました。次のコードは、2つの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();
4

1 に答える 1

11

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

の異なるIdCourseBookings

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

resultXDocument違いの要約を含むようになりました:

<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>
于 2012-05-07T21:00:45.157 に答える