2009-11-03 140 views
1

我正在做一些使用xlinq的变换,其中一些变换可能导致在文档中留下空元素。使用xlinq删除所有空元素

一旦我完成了所有这些转换,我如何查询所有空元素的xdocument?

换句话说;如果我删除所有<a>标签,而这些标签恰好是<li>标签中的唯一元素,那么如何删除空的<li>

前:

XDocument.Parse(@"<body> 
    <ul><li><a href="#">Joy</a></li></ul> 
    <p>Hi.</p> 
</body>").Descendants("a").Remove(); 

后:

<body> 
    <ul><li/></ul> 
    <p>Hi.</p> 
</body> 

我宁愿:

<body> 
    <p>Hi.</p> 
</body> 

回答

10

检查元素doesn't have attributedoesn't have elements是否不够。你需要检查一个元素是否真的是空的(绝对没有内容)。 XElement有一个属性,实际上可以帮助你做到这一点 - XElement.IsEmpty

var document = XDocument.Parse(@"<body><ul><li><a href='#'>Joy</a></li></ul><p>Hi.</p></body>"); 
document.Descendants("a").Remove(); 

var emptyElements = from element in document.Descendants() 
        where element.IsEmpty 
        select element; 

while (emptyElements.Any()) 
    emptyElements.Remove(); 
0

我能想出的最好的是...

var emptyElements = 
    from element in document.Descendants() 
    where !element.Attributes().Any() && !element.Elements().Any() 
    select element; 


while(emptyElements.Any()) 
    emptyElements.Remove(); 

然后我意识到这是一个坏主意,它消除了太多,但我没有花时间弄清楚为什么。

1

给予的XmlNodeList这一功能的尝试此代码 希望这将工作从XML文件

public static XmlNode RemoveNullElement(XmlNodeList xmlNodeList) 
    { 
     if (xmlNodeList.Count > 0) 
     { 
      foreach (XmlNode xmlnode in xmlNodeList) 
      { 
       RemoveNullChildAndAttibute(xmlnode); 
       return xmlnode; 
      } 
     } 

     return null; 
    } 


    public static void RemoveNullChildAndAttibute(XmlNode xmlNode) 
    { 
     if (xmlNode.HasChildNodes) 
     { 
      for (int xmlNodeCount = xmlNode.ChildNodes.Count - 1; xmlNodeCount >= 0; xmlNodeCount--) 
      { 
       RemoveNullChildAndAttibute(xmlNode.ChildNodes[xmlNodeCount]); 
      } 
     } 
     else if (xmlNode.Attributes.Count == 0) 
     { 
      if (xmlNode.ParentNode != null) 
      { 
       xmlNode.ParentNode.RemoveChild(xmlNode); 
      } 
     } 
    } 
0

这里接受的答案是不完全正确删除所有空的元素和属性。具体来说,它只会删除<foo />形式的元素,并会留下像<foo></foo>这样的元素。

因此,这里是一个完整的解决方案:

public static void RemoveEmptyDescendants(this XNode node) 
{ 
    var empty = from e in node.Descendants() 
       where !e.Nodes().Any() && !e.Attributes().Any() 
       select e; 

    while (empty.Any()) 
    { 
     empty.Remove(); 
    } 
} 
0

检查都为IsEmpty和HasAttributes是更有帮助。

 var emptyElements = document.Descendants() 
          .Where(element => element.IsEmpty 
              && !element.HasAttributes); 
     while (emptyElements.Any()) 
     { 
      emptyElements.Remove(); 
     } 

对于只有属性的元素,IsEmpty将返回true。例如:

 <Participant xsi:nil="true"/>