问题
Fairly new to Linq to XML How does one remove xml node( recursively using relation ) and save the document.
Structure of the xml cannot be altered as it comes from service.Below is the xml from a tasks service. Every task can have nested tasks for which there might be one or more nested tasks. Nesting is intended to be upto N level
.
When one of parent tasks are removed using linq to xml how do i remove all of it's children?
How do i know all the nodes where successfully removed?
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>
In above xml when taskId=2
is removed, it's sub-tasks namely Id = 3
should be removed. Since 3
is removed it's subtasks 4
and 5
should be removed as well.
回答1:
I'm going to assume that with the 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>
If Task ID=2
is removed, here is one solution:
// 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();
}
}
Result:
<Tasks>
<Task ID="1">Clean the Room</Task>
<Task note="test node" />
<Task ID="a" note="test node" />
</Tasks>
回答2:
Use following answer
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");
来源:https://stackoverflow.com/questions/10378498/recursively-remove-xml-nodes-using-linq-to-xml