使用 Linq to XML 递归删除 xml 节点

本文关键字:删除 xml 节点 递归 XML Linq to 使用 | 更新日期: 2023-09-27 18:32:45

Linq到XML来说相当新 如何删除xml节点(递归使用关系)并保存文档。

XML 的结构无法更改,因为它来自服务。下面是来自任务服务的 xml。每个任务都可以有嵌套任务,其中可能有一个或多个嵌套任务。嵌套旨在达到 N level .

  • 当使用 linq to xml 删除其中一个父任务时,如何删除它的所有子任务?

  • 我如何知道成功删除的所有节点?

Xml:

<Tasks>
  <Task ID="1">Clean the Room</Task>
  <Task ID="2">Clean the Closet</Task>
  <Task ID="3" ParentId="2">Remove the toys</Task>
  <Task ID="4" ParentId="3">Stack action Figures on Rack</Task>
  <Task ID="5" ParentId="3">Put soft toys under bed</Task>
</Tasks>

在上面的xml中,当删除taskId=2时,它的子任务即Id = 3应该被删除。由于删除了3,因此它的子任务45也应该被删除。

使用 Linq to XML 递归删除 xml 节点

我将假设使用 xml :

<Tasks> 
  <Task ID="1">Clean the Room</Task>
  <Task ID="2">Clean the Closet</Task>
  <Task ID="3" ParentId="2">Remove the toys</Task>
  <Task ID="4" ParentId="3">Stack action Figures on Rack</Task>
  <Task ID="5" ParentId="3">Put soft toys under bed</Task>
  <Task note="test node" />
  <Task ID="a" note="test node" />
</Tasks>

如果删除Task ID=2,这里有一个解决方案:

// tasks = XDocument.root;
public static void RemoveTasksAndSubTasks(XElement tasks, int id)
{
  List<string> removeIDs = new List<string>();
  removeIDs.Add(id.ToString());
  while (removeIDs.Count() > 0)
  {
    // Find matching Elements to Remove
    // Check for Attribute, 
    // so we don't get Null Refereence Exception checking Value
    var matches = 
        tasks.Elements("Task")
             .Where(x => x.Attribute("ID") != null
                         && removeIDs.Contains(x.Attribute("ID").Value));
    matches.Remove();
    // Find all elements with ParentID 
    // that matches the ID of the ones removed.
    removeIDs = 
        tasks.Elements("Task")
             .Where(x => x.Attribute("ParentId") != null
                         && x.Attribute("ID") != null
                         && removeIDs.Contains(x.Attribute("ParentId").Value))
             .Select(x => x.Attribute("ID").Value)
             .ToList();
  }
}

结果:

<Tasks> 
  <Task ID="1">Clean the Room</Task>
  <Task note="test node" />
  <Task ID="a" note="test node" />
</Tasks>

使用以下答案

XDocument doc = XDocument.Load("task.xml");
var q = from node in doc.Descendants("Task")
        let attr = node.Attribute("ID")
        let parent = node.Attribute("ParentId")
        where ((attr != null && attr.Value == "3") || (parent != null && parent.Value == "3"))
        select node;
q.ToList().ForEach(x => x.Remove());
doc.Save("output.xml");