簡體   English   中英

用C#刪除XML節點的最快方法

[英]Fastest way to remove XML nodes with C#

假設我有一個內存XElement,如下所示:

<ROOT>
    <CHILD1 />
    <CHILD1 />
    <CHILD2 />
    <CHILD2 />
    <CHILD1 />
    <CHILD1 />
    <CHILD3 />
    <CHILD3 />
</ROOT>

除最后一個節點外,所有CHILD1節點都必須刪除。

該樹大約有100萬個節點,其中70%是CHILD1節點。 及時刪除這些未使用的節點的最有效方法是什么? 我嘗試了以下方法:

List<XElement> remNodes = root.Elements("CHILD1").ToList();
remNodes.RemoveRange(0, remNodes.Length - 1)

以及古老而又簡單的方法:

XElement[] remNodes = root.Elements("CHILD1").ToArray();
for (i=0;i<remNodes.Length-1;i++) remNodes[i].Remove();

兩者都花了太多時間(〜5小時)。 有更快的方法嗎?

更新1

嘗試保存最后一個節點並按如下所示刪除:

XElement savedNode = remNodes.Last();
savedNode.Save("to_file");
root.Elements("CHILD1").Remove();

但是看起來所花費的時間是相同的。

更新2

最后,我最終及時完成了任務(不到1分鍾)。 我使用了一種將有效節點保存到文件中的方法,然后刪除整個樹並使用保存的節點重新加載樹。 感謝@Matthew Haugen的想法。 您介意添加答案嗎?

謝謝。

嘗試,

root.Elements("CHILD1").Reverse().Skip(1).Remove();

我把這個放在一起。 200000個子元素。 不會花太長時間,但我不確定您嘗試使用多少個。

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Linq;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            string data = DummyData();

            //DeleteNodes("child1", data);
            DeleteNodes2("child1", data);

            Console.ReadLine();
        }

        static void DeleteNodes(string node, string xml)
        {
            var values = new HashSet<string>();
            var xmlDocument = XDocument.Parse(xml);

            foreach (var n in xmlDocument.Root.Elements(node).ToList())
            {
                if (!values.Add((string)node))
                    n.Remove();
            }
        }

        static void DeleteNodes2(string node, string xml)
        {
            var xmlDocument = XDocument.Parse(xml);

            xmlDocument.Root
                     .Elements(node).GroupBy(g => g).SelectMany(f => f).Reverse().Skip(1).Remove();

            //Test to see how many are left
            var duplicates = xmlDocument.Root
                     .Elements(node).GroupBy(g => g).ToList(); 
        }

        static string DummyData()
        {
            Random r = new Random();
            TextWriter w = new StringWriter();


            var writer = new XmlTextWriter(w);
            writer.Formatting = Formatting.Indented;
            writer.WriteStartElement("root");

            for (int i = 0; i < 200000; i++)
            {
                int rand = r.Next(3);
                writer.WriteStartElement(string.Format("child{0}", rand.ToString()));
                writer.WriteEndElement();
            }

            writer.WriteEndElement();

            return w.ToString();
        }
    }
}

如果確實更快,則應歸功於Chuck。 這只是他的建議的一部分。

最后,我最終及時完成了任務(不到1分鍾)。 我使用了一種將有效節點保存到文件中的方法,然后刪除整個樹並使用保存的節點重新加載樹。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM