C# 中的程序化 XML 差异/合并

Posted

技术标签:

【中文标题】C# 中的程序化 XML 差异/合并【英文标题】:Programmatic XML Diff / Merge in C# 【发布时间】:2012-12-29 18:33:27 【问题描述】:

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

这种方法的问题是KDiff是一个行比较程序,不知道XML的方式(如Nodes等)

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

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

    如果当前工作 XML 有一个源 XML 没有的节点,请将其删除。 如果源 XML 有一个当前工作 XML 没有的节点,请添加它。 如果两者具有相同的节点且值不同,则优先使用 Source XML 的值,除非 Source XML 的值设置为“UseExistingValue”。

例如,这里是“源”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】:

经过几天的折腾,我找到了一个我认为适合我的解决方案。也许它也适用于其他人。

The MS XML Diff and Patch tool 是一个可行的选择。当您将第一个文件与第二个文件进行比较时,它会创建一个 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

【讨论】:

要从 NuGet 安装 XMLDiffPatch,请参阅 nuget.org/packages/XMLDiffPatch 对我来说效果很好,但我确实遇到了与 cmets 相关的错误(即使未指定 XmlDiffOptions.IgnoreComments,它也会忽略 cmets)

以上是关于C# 中的程序化 XML 差异/合并的主要内容,如果未能解决你的问题,请参考以下文章

如何从 URL 读取 Windows 应用程序中的大量 xml 文件(从 Windows 应用程序到服务器的多个请求)c#

C# 应用程序未保存到 xml [关闭]

在 C# 中合并两个 XML 文件

C# .Net 4.0 应用程序中托管的 C++ ActiveX 控件中的 Xml.Serializer 非法强制转换异常

C# XML 字符串编码问题

C#使用操作系统默认程序打开pdf,支持.NET Core跨平台,无视平台差异