XML:如何删除所有没有属性的节点或子元素

我有一个像这样的xml文档:

      

这里是我要删除的节点,因为它没有子元素和元素,也没有任何属性。

使用XPath表达式可以找到没有属性或子节点的所有节点。 然后可以从xml中删除它们。 正如Sani指出的那样,您可能必须递归执行此操作,因为如果删除其内部节点,node_1_1将变为空。

 var xmlDocument = new XmlDocument(); xmlDocument.LoadXml( @"     "); // select all nodes without attributes and without children var nodes = xmlDocument.SelectNodes("//*[count(@*) = 0 and count(child::*) = 0]"); Console.WriteLine("Found {0} empty nodes", nodes.Count); // now remove matched nodes from their parent foreach(XmlNode node in nodes) node.ParentNode.RemoveChild(node); Console.WriteLine(xmlDocument.OuterXml); Console.ReadLine(); 

像这样的东西应该这样做:

 XmlNodeList nodes = xmlDocument.GetElementsByTagName("Node1"); foreach(XmlNode node in nodes) { if(node.ChildNodes.Count == 0) node.RemoveAll; else { foreach (XmlNode n in node) { if(n.InnerText==String.Empty && n.Attributes.Count == 0) { n.RemoveAll; } } } } 

此样式表使用标识转换,其中空模板匹配没有节点或属性的元素,这将阻止它们被复制到输出:

            

要对所有空子节点执行此操作,请使用for循环(不是foreach)并按相反顺序。 我把它解决为:

 var xmlDocument = new XmlDocument(); xmlDocument.LoadXml(@"        "); RemoveEmptyNodes(xmlDocument ); private static bool RemoveEmptyNodes(XmlNode node) { if (node.HasChildNodes) { for(int I = node.ChildNodes.Count-1;I >= 0;I--) if (RemoveEmptyNodes(node.ChildNodes[I])) node.RemoveChild(node.ChildNodes[I]); } return (node.Attributes == null || node.Attributes.Count == 0) && node.InnerText.Trim() == string.Empty; } 

递归调用(与其他解决方案类似)消除了xPath方法的重复文档处理。 更重要的是,代码更易读,更容易编辑。 双赢。

因此,此解决方案将删除 ,但也会正确删除

更新:使用以下Linq实现发现性能显着提高。

 string myXml = @"        "); XElement xElem = XElement.Parse(myXml); RemoveEmptyNodes2(xElem); private static void RemoveEmptyNodes2(XElement elem) { int cntElems = elem.Descendants().Count(); int cntPrev; do { cntPrev = cntElems; elem.Descendants() .Where(e => string.IsNullOrEmpty(e.Value.Trim()) && !e.HasAttributes).Remove(); cntElems = elem.Descendants().Count(); } while (cntPrev != cntElems); } 

循环处理需要删除父项的情况,因为它的唯一子项已被删除。 由于幕后的IEnumerable实现,使用XContainer或衍生产品往往会有类似的性能提升。 这是我最喜欢的事情。

在任意68MB xml文件上, RemoveEmptyNodes往往需要大约90秒,而RemoveEmptyNodes2往往需要大约1秒。