在C#中扩展大型XML文件(.net 2.0)

时间:2012-06-06 19:53:22

标签: c# xml diff

我有点不得不使用.Net 2.0,所以LINQ xml不可用,虽然我会对它的比较感兴趣......

我必须编写一个内部程序来下载,提取和比较一些基本上是构建配置的大型XML文件(每个大约10兆)。我首先尝试使用库,例如​​Microsoft's XML diff/patch,但是比较文件需要2-3分钟,即使忽略了空格,命名空间等等(我测试过每次忽略一个,试图弄清楚是什么最快)。我试图实现自己的想法 - 来自XmlDocument对象的节点列表,根的直接后代的键的字典(顺便说一下,45000个子节点),指向int以指示XML文档中的节点位置......所有至少要跑2分钟。

我的最终实现在1-2秒内完成 - 我用几行上下文进行了系统进程调用diff并保存了这些结果(我们的开发机器包括cygwin,谢天谢地)。

我不禁想到有一种更好的,特定于XML的方法可以做到这一点,就像纯文本差异一样快 - 特别是因为我真正感兴趣的是Name元素,即孩子为了我的目的,每个直接后代都可以扔掉4/5的文件(我们只需要知道包含哪些文件,而不是任何涉及语言或版本的文件)

因此,像XML一样流行,我相信那里的人不得不做类似的事情。什么是比较这些大型XML的快速有效方法? (优选开源或免费)

编辑:节点的样本 - 我只需要找到缺少的Name元素(还有超过45k的节点)

<file>
     <name>SomeFile</name>
     <version>10.234</version>
     <countries>CA,US</countries>
     <languages>EN</languages>
     <types>blah blah</types>
     <internal>N</internal>
</file>

2 个答案:

答案 0 :(得分:0)

XmlDocument source = new XmlDocument();
source.Load("source.xml");
Dictionary<string, XmlNode> files = new Dictionary<string, XmlNode>();
foreach(XmlNode file in source.SelectNodes("//file"))
    files.Add(file.SelectSingleNode("./name").InnerText, file);

XmlDocument source2 = new XmlDocument();
source2.Load("source2.xml");
XmlNode value;
foreach(XmlNode file in source2.SelectNodes("//file"))
    if (files.TryGetValue(file.SelectSingleNode("./name").InnerText, out value))
      // This file is both in source and source2.
    else
      // This file is only in source2.

我不确定你想要什么,我希望这个例子可以帮助你完成任务。

答案 1 :(得分:0)

差异化XML可以通过多种方式完成。不过,你对细节并不十分具体。发现的是文件很大,你只需要4/5的信息。

那么算法如下:

  • 将文档规范化并减少重要信息。
  • 保存结果。
  • 比较结果。

实施

  • 使用有效的XmlReader API来生成信息的纯文本表示。为什么是纯文本表示?因为diff工具的前提是假设有纯文本。我们的眼球也是如此。为什么XmlReader?您可以使用SAX,它具有内存效率,但XmlReader更有效。至于那个纯文本文件的精确规格......你只是没有包含足够的信息。
  • 将纯文本文件保存到某个临时目录。
  • 使用命令行差异实用程序(如GnuWin32 diff)来获取一些差异输出。是的,我知道,不是纯粹和正确的,但开箱即用,没有编码可做。如果您熟悉一些C#diff API(我不是),那么,当然要使用该API。
  • 删除临时文件。 (或者如果你要重复使用它们,可以选择保留它们。)