C#中的编程XML差异/合并

时间:2013-01-15 15:51:55

标签: c# xml merge diff

目前,我正在管理一个包含多个XML配置文件的软件。当发布新版本的软件时,有时基本配置文件会发生变化,我们目前在启动时会调用软件KDiff。如果它检测到更改,则会提示用户选择更改。

这种方法的问题在于KDiff是比较程序的行,而不是知道XML的方式(如节点等)

理想情况下,我想以编程方式使用C#中的库(因为我们是一个MS商店),可以对两个XML文件进行Diff:源XML和当前工作XML。

然后使用一些简单的规则将两者合并在一起:

  1. 如果当前工作XML具有源XML不具有的节点,请将其删除。
  2. 如果源XML有一个当前工作XML没有的节点,请添加它。
  3. 如果两者具有相同的节点且值不同,则支持Source XML的值,除非Source XML的值设置为“UseExistingValue”。
  4. 例如,这是“源”XML:

    <Configuration>
      <Items>
         <Item Id="1" Position="true">
           <Location X="UseExistingValue" Y="UseExistingValue" Z="UseExistingValue" />
    
           <Something/>
           <SomethingElse/>
         </Item>
       </Items>
     </Configuration>
    

    这是“当前工作”XML:

    <Configuration>
      <Items>
        <Item Id="1" Position="false">
          <Location X="123" Y="234" Z="345" />
          <Another/>
          <Something/>
    
        </Item>
      </Items>
    </Configuration>
    

    合并的版本看起来像:

    <Configuration>
      <Items>
        <Item Id="1" Position="true">
          <Location X="123" Y="234" Z="345" />
    
          <Something/>
          <SomethingElse/>
        </Item>
      </Items>
    </Configuration>
    

    我查看了MS XML Diff and Patch Tool,它肯定会将文件合并在一起,但不允许我想要定义的编程规则。

    XMLUnit for Java devs似乎很有希望,但它的.NET版本似乎不发达,这是不幸的。

    任何人对可编写脚本的XML Diff / Merge工具和/或.NET库(付费或免费)有任何建议吗?

    感谢。

1 个答案:

答案 0 :(得分:21)

经过几天的捣乱,我找到了一个我觉得适合我的解决方案。也许它也适用于其他人。

The MS XML Diff and Patch tool是一个可行的选择。当您针对第二个文件对第一个文件进行Diff时,它会创建一个XML“DiffGram”,列出它在两个XML文件之间检测到的更改。

为了处理我上面列出的所有3条规则,我将这两个文件向一个方向扩展,然后使用Linq-to-XML打开DiffGram文件,并删除所有“添加”和“删除”行。

XNamespace xd = "http://schemas.microsoft.com/xmltools/2002/xmldiff";
var doc = XDocument.Load(_diffGramFile);
doc.Root.DescendantsAndSelf(xd + "add").Remove();
doc.Root.DescendantsAndSelf(xd + "remove").Remove();

然后,我将这个已编辑的diffgram修补(合并)到第一个文件,并创建了一个部分合并的临时文件。这将处理规则1和2。

接下来,我将部分合并的文件与所使用的第一个文件进行了比较。然后打开新的DiffGram并删除所有对“UseExistingValue”的更改引用。

var newdoc = XDocument.Load(_diffGramFile);
newdoc.Root.DescendantsAndSelf(xd + "change")
      .Where(x => x.Value == "UseExistingValue").Remove();

并将此编辑过的DiffGram与部分合并的文件合并,该文件负责规则3.将其保存到XML然后根据上面定义的规则生成合并的最终XML。

希望这可以帮助其他人。

提示:安装XmlDiffPatch库后,可以在C:\ Windows \ assembly \ GAC \ XmlDiffPatch \ 1.0.8.28__b03f5f7f11d50a3a \ XmlDiffPatch.dll中找到XmlDiffPatch DLL