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

本文关键字:删除 元素 文件 XML | 更新日期: 2023-09-27 18:31:36

我有一个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),2-5分钟需要100%的CPU。

您知道如何改进它并使其更好吗?

我有点绝望。

谢谢!

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

听起来你只希望删除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;

是的,就是这样。我已经在一些虚拟数据广告上对此进行了测试,它工作正常。

文档1:

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

初始文档2:

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

最终文档2:

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

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

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

看起来你正在与两件事作斗争:

  1. 对于这种任务,XML是一个糟糕的选择(但我知道它可能不是你的选择)
  2. 将整个文档读成XDocument(或XmlDocument)是昂贵且不必要的

要摆脱 (2),请尝试使用较低级别的方法XmlReader(这可能还不够)或更低级别的方法,如 Java-nese SAX 或 Perl-ish XML:Twig,它们为您提供基于事件的 XML 解析而无需构建文档结构 - 但我不知道这样的 .net 库。有一个用于 .NET 的 SAX 解析器端口,但我不知道它有多好。

当然,您可以节省大量时间保留以前解析的文档中的数据,而只解析新文档(但我相信您知道这一点)

你现在要做的是,对于字典 1 中这数百万个事件中的每一个,你迭代字典 2 中的数百万个事件,将字典 1 中的每个事件与字典 2 中的每个事件进行比较。这进行了数千亿次比较!这不是必需的。将第一个 XML 中的所有事件放入字典。然后,对于第二个 XML 中的每个事件,查看字典中是否也存在相同的事件。如果是,请将其删除。在字典中搜索比在第一个 XML 中遍历数百万个事件中的每一个要快得多,并且也会使您的程序更快。