如何使用LINQ删除XElement而不包括它的子节点?

4
这里是我的XML
<A>
    <B  id="ABC">
      <C name="A" />
      <C name="B" />     
    </B>
    <X>
     <B id="ZYZ">
      <C name="A" />
      <C name="B" />
     </B>
    </X>
</A>

我正在使用以下代码来删除<X>节点,而不会删除其后代/子节点:

XDocument doc = XDocument.Load("D:\\parsedXml.xml");
doc.Descendants("A").Descendants("X").Remove();

但是需要删除整个<X>块。

预期输出:

<A>
    <B  id="ABC">
      <C name="A" />
      <C name="B" />     
    </B>
     <B id="ZYZ">
      <C name="A" />
      <C name="B" />
     </B>
</A>
4个回答

5
var x = doc.Root.Element("X");
x.Remove();
doc.Root.Add(x.Elements());

2
我建议将内容添加到 x 的上一个父元素中。 - Piotr Zierhoffer
2
同时还支持多个 X 元素。 - Andrei V

4

批准的答案总是将子元素添加到文档的末尾。如果您需要在文档中间删除条目并保留子元素在原位,请按照以下步骤操作:

x.AddAfterSelf(x.Nodes());
x.Remove();

以下代码会删除所有的<x>节点,但保留其子节点在正确的位置:
while (doc.Descendants("x").Count() > 0)
{
    var x = doc.Descendants("x").First();
    x.AddAfterSelf(x.Nodes());
    x.Remove();
}

0
如果节点名称已被弃用且不能在整个文档中使用,则只需使用ReplaceWith:
var xNode = doc.Descendants("x");
for (int i = 0; i < xNode.Count; i++)
{
    xNode[i].ReplaceWith(xNode[i].Nodes());
}

0
稍微改进一下Mike的有用答案。
之所以不能只迭代一次Descendants,是因为AddAfterSelf()会创建副本。在第一次删除后,您正在迭代已删除元素的子级,而不是它们在文档中的替换项。
但是,如果您反向迭代它们,则任何复制的子级都已经被处理过了,因此您可以通过单个传递来完成:
foreach(var x in xdoc.Descendants("x").Reverse())
{
    x.AddAfterSelf(x.Nodes());
    x.Remove();
}

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