【问题标题】:Removing nodes from XDocument从 XDocument 中删除节点
【发布时间】:2010-07-09 18:24:26
【问题描述】:

这会从文档中删除所有元素:

        XDocument document = XDocument.Load(inputFile);
        foreach (XElement element in document.Elements())
        {
            element.Remove();
        }
        document.Save(outputFile);

这没有任何作用:

        XDocument document = XDocument.Load(inputFile);
        foreach (XElement element in document.Elements())
        {
            //element.Remove();
            foreach (XElement child in element.Elements())
                child.Remove();
        }
        document.Save(outputFile);

我在这里遗漏了什么吗?既然这些都是对 XDocument 中元素的引用,那么这些更改不应该生效吗?是否有其他方法可以从 XDocument 中删除嵌套的子项?

谢谢!

【问题讨论】:

  • 你调试过代码吗?您确定 element.Elements() 正在返回子元素吗?只是寻找有关您所看到的确切情况的更多信息。
  • @jrista 它正在返回子元素,但问题似乎在于枚举器在 .Remove() 之后的行为不同。
  • 是的,这正是我所期望的。当您修改集合时,枚举器通常会抛出异常,因为它们非常依赖于底层集合的稳定性才能正常运行。我真的很惊讶你可以在使用 foreach/enumerator 删除节点后继续。我通常建议使用 while 循环(或者可能是 for...,但那更复杂),而不是 foreach。
  • @jrista 当你这样说时,它更有意义。无声的失败总是让我头疼:/
  • 是的,我讨厌无声的失败。我真的很惊讶这里发生的事情,像往常一样,.NET 中的迭代 + 集合修改意味着抛出异常。我在反射器中挖掘了 XDocument 代码,.Remove() 的工作方式非常迂回,并且涉及在某一点创建一个内部列表。我猜这就是为什么删除成功而不是抛出的原因......但由于集合的状态发生变化,它肯定会弄乱枚举,而枚举器不知道这一点。

标签: c# xml linq


【解决方案1】:

显然,当您遍历 element.Elements() 时,在其中一个子节点上调用 Remove() 会导致枚举数为 yield break。遍历element.Elements().ToList() 解决了这个问题。

【讨论】:

  • 那是 XPath 特有的吗?
  • @Neo 以什么方式?正如上面jirsta 所指出的,当底层集合发生变化时,大多数枚举器都会中断。
  • 是的,我知道 InvalidOperationException 正常发生。我的问题是关于yield break。这是否特定于 XPath 相对于 @jrista 的评论无声失败?
【解决方案2】:

这是使用 System.Xml.XPath 的另一种方式的示例(更改 xpath 查询以满足您的需要):

const string xml = 
    @"<xml>
        <country>
            <states>
                <state>arkansas</state>
                <state>california</state>
                <state>virginia</state>
            </states>
        </country>
    </xml>";
XDocument doc = XDocument.Parse(xml);
doc.XPathSelectElements("//xml/country/states/state[.='arkansas']").ToList()
   .ForEach(el => el.Remove());;
Console.WriteLine(doc.ToString());
Console.ReadKey(true);

【讨论】:

    【解决方案3】:

    当使用XDocument 时,试试这个:

    XDocument document = XDocument.Load(inputFile);
    foreach (XElement element in document.Elements())
    {
         document.Element("Root").SetElementValue(element , null);
    }
    document.Save(outputFile)
    

    问候, 托德

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-04-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-15
      相关资源
      最近更新 更多