删除没有子节点的父节点

我有一个与从xml文件中删除特定节点有关的问题。

这是我的XML示例:

                                   

我想删除节点nodeB="toRemove"而不删除此节点的子节点。 之后我需要使用nodeB attribute="placeHolder"做同样的事情。 结果的一部分看起来像这样:

           

我一直在尝试这样的代码来实现:

  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); 

我能够找到具有所需属性toRemove或placeHolder的节点,但是我无法将此节点的子节点向上移动一级。 在这种情况下你能帮我吗? 它可以是Linq,XDocument,XmlReader的解决方案,但我更喜欢使用XmlDocument。 感谢您提前给我提供的任何帮助。

编辑:

在这种情况下,我使用了稍微修改过的代码(以保持顺序),Chuck Savage写道。 一旦删除

    

然后再做同样的事情

   

这是稍微修改过的代码

  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); 

@MiMo提供的xslt方法在这种情况下也非常有用。

使用Linq-to-XML和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); 

注意: System.Xml.XPath提供了XPath

注意2:您可以使用这些扩展名转换为/从XmlDocument转换,因为您更喜欢XmlDocument。

问题是你无法在枚举子节点时修改文档节点 – 你应该创建新节点而不是尝试修改现有节点,这使用XmlDocument会变得有点棘手。

执行此类转换的最简单方法是使用XSLT,即应用此XSLT:

              

输入文件的输出是:

                           

应用XSLT的代码很简单:

  XslCompiledTransform transform = new XslCompiledTransform(); transform.Load(@"c:\temp\nodes.xslt"); transform.Transform(@"c:\temp\nodes.xml", @"c:\temp\nodes-cleaned.xml"); 

如果不可能(或不希望)为XSLT使用外部文件,则可以从字符串中读取它:

  string xsltString = @"            "; XslCompiledTransform transform = new XslCompiledTransform(); using (StringReader stringReader = new StringReader(xsltString)) using (XmlReader reader = XmlReader.Create(stringReader)) { transform.Load(reader); } transform.Transform(@"c:\temp\nodes.xml", @"c:\temp\nodes-cleaned.xml"); 

我知道它是一个老问题,但我直接用XmlDocument写了这个。

如果有人喜欢这样做,请添加它:

 XmlNode child_to_remove = parent.ChildNodes[i]; // get the child to remove // move all the children of "child_to_remove" to be the child of their grandfather (== parent) while(child_to_remove.HasChildNodes) parent.InsertBefore(child_to_remove.ChildNodes[0], child_to_remove); parent.RemoveChild(child_to_remove); 

就是这样:-),希望它能帮到任何人。