remove parent node without childs nodes

c#, linq-to-xml, xml, xml-parsing, xpath

Solution

Using Linq-to-XML and your XPath,

XElement root = XElement.Load(XmlFilePathSource); // or .Parse(string)
var removes = root.XPathSelectElements("//nodeB[@attribute=\"toRemove\"]");
foreach (XElement node in removes.ToArray())
{
    node.AddBeforeSelf(node.Elements());
    node.Remove();
}
root.Save(XmlFilePathSource);

Note: XPath is available in `System.Xml.XPath`

Note2: You can convert to/from XmlDocument using these extensions since you prefer XmlDocument.

Problem

I have a question related to removing specific nodes from xml file. Here is my sample of XML: ``` <?xml version="1.0" encoding="UTF-8"?> <root> <nodeA attribute="1"> <nodeB attribute="table"> <nodeC attribute="500"></nodeC> <nodeC attribute="5"></nodeC> </nodeB> <nodeB attribute="3"> <nodeC attribute="4"></nodeC> <nodeC attribute="5"></nodeC> <nodeC attribute="5"></nodeC> </nodeB> <nodeB attribute="placeHolder"> <nodeB attribute="toRemove"> <nodeB attribute="glass"></nodeB> <nodeE attribute="7"></nodeE> <nodeB attribute="glass"></nodeB> <nodeB attribute="glass"></nodeB> </nodeB> </nodeB> <nodeB attribute="3"> <nodeC attribute="4"></nodeC> <nodeC attribute="5"></nodeC> <nodeC attribtue="5"></nodeC> </nodeB> <nodeB attribute="placeHolder"> <nodeB attribute="toRemove"> <nodeB attribute="glass"></nodeB> <nodeE attribute="7"></nodeE> <nodeB attribute="glass"></nodeB> <nodeB attribute="glass"></nodeB> </nodeB> </nodeB> </nodeA> </root> ``` I would like to remove node `nodeB="toRemove"` without removing childrens of this node. After that I need to do same thing with `nodeB attribute="placeHolder"`. Part of result would look like that: ``` <nodeB attribute="3"> <nodeC attribute="4"></nodeC> <nodeC attribute="5"></nodeC> <nodeC attribtue="5"></nodeC> </nodeB> <nodeB attribute="glass"></nodeB> <nodeE attribute="7"></nodeE> <nodeB attribute="glass"></nodeB> <nodeB attribute="glass"></nodeB> ``` I have been trying code like this to achive that: ``` XmlNodeList nodeList = doc.SelectNodes("//nodeB[@attribute=\"toRemove\"]"); foreach (XmlNode node in nodeList) { foreach (XmlNode child in node.ChildNodes) { node.ParentNode.AppendChild(child); } node.ParentNode.RemoveChild(node); } doc.Save(XmlFilePathSource); ``` I am able to locate node with desired attribute toRemove or placeHolder, however I am not able to move children of this nodes up by one level. Could you help me in this case? It can be solution with Linq, XDocument, XmlReader but I prefer working with XmlDocument. Thank you for any help you could provide me in advance. EDIT: In this case I have used slightly modified code(to preserve order) that Chuck Savage wrote bellow. Once to remove ``` <nodeB attribute="toRemove"> </nodeB> ``` and then do the same with ``` <nodeB attribute="placeHolder"></nodeB> ``` Here is slightly modified code ``` XElement root = XElement.Load(XmlFilePathSource); var removes = root.XPathSelectElements("//nodeB[@attribute=\"toRemove\"]"); foreach (XElement node in removes.ToArray()) { node.Parent.AddAfterSelf(node.Elements()); node.Remove(); } root.Save(XmlFilePathSource); ``` xslt approach provided by @MiMo is very useful as well in this case.

Original source