使用C#如何从XML中删除没有属性的空元素?

3

根据StackOverflow上的先前答案,我正在使用以下语句来删除所有空元素(除了那些具有属性的元素):

XDocument xdoc = XDocument.Parse(xmlString);

xdoc.Descendants()
    .Where(e => !e.HasAttributes && (e.IsEmpty || String.IsNullOrWhiteSpace(e.Value)))
    .Remove();

当对以下XML运行时:
<MESSAGE>
    <RELATIONSHIPS1>
        <RELATIONSHIP1 from="10017" to="1"/>
    </RELATIONSHIPS1>
    <RELATIONSHIPS2>
        <RELATIONSHIP2 from="10017" to="1"></RELATIONSHIP2>
    </RELATIONSHIPS2>
    <RELATIONSHIPS3>
        <RELATIONSHIP3 from="10017" to="1">test</RELATIONSHIP3>
    </RELATIONSHIPS3>
    <RELATIONSHIPS4 attr="test">
        <RELATIONSHIP4 from="10017" to="1"></RELATIONSHIP4>
    </RELATIONSHIPS4>
    <EXTENSION a1="1" a2="2"/>
    <FLOOD>
        <FLOOD_RESPONSE>
            <PROPERTY>
                <PROPERTY_DETAIL/>
                <PROPERTY_DETAIL></PROPERTY_DETAIL>
             </PROPERTY>
        </FLOOD_RESPONSE>
    </FLOOD>
</MESSAGE>

我期望得到以下结果:
<MESSAGE>
    <RELATIONSHIPS1>
        <RELATIONSHIP1 from="10017" to="1"/>
    </RELATIONSHIPS1>
    <RELATIONSHIPS2>
        <RELATIONSHIP2 from="10017" to="1"></RELATIONSHIP2>
    </RELATIONSHIPS2>
    <RELATIONSHIPS3>
        <RELATIONSHIP3 from="10017" to="1">test</RELATIONSHIP3>
    </RELATIONSHIPS3>
    <RELATIONSHIPS4 attr="test">
        <RELATIONSHIP4 from="10017" to="1"></RELATIONSHIP4>
    </RELATIONSHIPS4>
    <EXTENSION a1="1" a2="2" />
</MESSAGE>

但是收到了以下内容:
<MESSAGE>
  <RELATIONSHIPS3>
    <RELATIONSHIP3 from="10017" to="1">test</RELATIONSHIP3>
  </RELATIONSHIPS3>
  <RELATIONSHIPS4 attr="test">
    <RELATIONSHIP4 from="10017" to="1"></RELATIONSHIP4>
  </RELATIONSHIPS4>
  <EXTENSION a1="1" a2="2" />
</MESSAGE>

有关嵌套的空元素带属性被移除的任何想法吗?

你需要使用递归,我不认为你可以通过LINQ进行递归。因此,你需要编写一个单独的递归函数。请参见https://dev59.com/oG445IYBdhLWcg3wiayV和https://dev59.com/e2Ei5IYBdhLWcg3wwemq和https://dev59.com/CWEi5IYBdhLWcg3wd8EF。 - Moby Disk
1个回答

3
请看MSDN上XElement.Value的描述:

获取或设置此元素的连接文本内容。

这意味着仅返回内部元素(仅限元素,而不包括属性)的值。例如,在您的 XML 中,有以下元素:

<RELATIONSHIPS1>
    <RELATIONSHIP1 from="10017" to="1"/>
</RELATIONSHIPS1>

这个元素的e.Value为空字符串,因此这个元素被移除了。
您可以运行这样的查询来删除您不需要的元素。基本上,您需要检查那些具有空值且没有任何属性的元素,并且所有后代元素都具有空值且没有属性:
xdoc.Descendants()
    .Where(e => !e.HasAttributes && 
                string.IsNullOrEmpty(e.Value) &&
                e.Descendants().All(f=>String.IsNullOrEmpty(f.Value) && !f.HasAttributes))
    .Remove();

2
太棒了。但是解决方案是什么? - User 12345678
太棒了!Descendants()函数会为您执行递归,所以我关于递归LINQ的评论是错误的。 - Moby Disk
“Where”谓词缺少String.IsNullOrEmpty(e.Value) && - Tom Blodget

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接