如何从2个XML文件中删除重复的元素?

时间:2012-04-19 19:09:11

标签: c# xml linq

我有一个XML解析到我的数据库,这个XML大小约为10MB,它包含数百万个元素。

每30-60秒更新一次,但只有几个元素,而不是全部。

为了以最快的方式解析数据库,我开发了一个函数来从2个XML文件中删除重复元素,这里是代码:

XDocument doc2 = XDocument.Parse(tempDoc.ToString());

var doc1 = new XDocument();
try
{
doc1 = XDocument.Load(bookieName + ".xml");
}
catch
{ }

try
{
var dict1 = doc1.Descendants("event").Select(el => el.ToString()).ToList();
var dict2 = doc1.Descendants("event").Select(el => el.ToString()).ToList();

foreach (var elem in dict1)
{
    if (dict2.Contains(elem))
    {
    if (dict2.Find(x => x == elem).ToString() == dict1.Find(x => x == elem).ToString())
    {
        doc2.Descendants("event").Where(x => x.ToString() == elem).Remove();
    }
    }
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}

return doc2;

问题是,它适用于小型XML文件,但对于大型XML文件(10MB),它需要100%的CPU,持续2-5分钟。

你知道我怎样才能改进它并使其更好?

我有点无望。

谢谢!

4 个答案:

答案 0 :(得分:0)

您可以通过在添加元素之前检查元素是否存在来解决。

并且您希望使用xml阅读器,以便在阅读时进行解析(以获得最佳性能)

答案 1 :(得分:0)

看起来你正在打两件事:

  1. XML对于这类任务来说是一个糟糕的选择(但我知道这可能不是你的选择)。
  2. 将整个文档读入XDocument(或XmlDocument)是昂贵的,没有必要
  3. 要摆脱(2),尝试使用较低级别的方法XmlReader(可能不够)或更低级别的方法,如Java-nese SAX或Perl-ish {{ 1}}它给你基于事件的XML解析而不构建文档结构 - 但是我不知道.net的这些库。有一个port of the SAX parser for .NET,但我不知道知道它有多好。

    当然,您可以节省大量时间来保存以前解析过的文档中的数据,并且只解析新文档(但我相信您知道)

答案 2 :(得分:0)

你现在所做的是,对于dict1中的这些数百万个事件中的每一个,你在dict2中迭代数百万个事件,将来自dict1的每个事件与来自dict2的每个事件进行比较。这使得成千上万的比较!这不是必需的。将所有事件从第一个XML放到字典中。然后,对于第二个XML中的每个事件,查看字典是否同样的事件也存在于第一个XML中。如果是,请将其删除。在字典中搜索比在第一个XML中浏览每一百万个事件要快得多,并且会使你的程序更快。

答案 3 :(得分:0)

听起来你只想删除doc2中的元素,如果它们也存在于doc1中,而不是相反。

您面临的问题是您的搜索效率非常低。如果您有几百万条记录,那么您可以通过几百万个平方记录进行有效搜索。

相反,您应该使用字典而不是列表来大大加快算法速度。

试试这个:

var dict1 = doc1.Descendants("event").ToDictionary(x => x.ToString(), x => x);
var dict2 = doc2.Descendants("event").ToDictionary(x => x.ToString(), x => x);

var xs = dict1.Keys.Intersect(dict2.Keys).Select(x => dict2[x]);

foreach (var x in xs)
{
    x.Remove();
}

return doc2;

是的,就是这样。我已经在一些虚拟数据广告上对此进行了测试,但它运行良好。

DOC1:

<doc>
  <event>bar</event>
  <event>foo</event>
</doc> 

初始doc2:

<doc>
  <event>foo</event>
  <event>qaz</event>
</doc> 

最终的doc2:

<doc>
  <event>qaz</event>
</doc>