替换xml元素

时间:2010-06-07 21:55:20

标签: c# .net linq-to-xml

我正在做类似的事情:

var results = from d in myDocument.Elements().Descendants("myName") select d;

foreach (var result in results){
   if (sth...){
      result.replace(myXElement);
   }
}

问题在于,当我替换一个元素时,我无法迭代到下一个元素,因为存在空引用。 (结果导致结果)。

有没有其他方法可以将该元素替换为另一个元素,并且仍然能够遍历该文档?

感谢您的帮助

stacktrace是:

System.NullReferenceException was unhandled
  Message="Odwołanie do obiektu nie zostało ustawione na wystąpienie obiektu."

Source="System.Xml.Linq"
  StackTrace:
       w System.Xml.Linq.XContainer.d__a.MoveNext()
       w System.Linq.Enumerable.WhereEnumerableIterator`1.MoveNext()
       w DocSorter.Merge.MergeFiles(String contentFilePath, String directoryPath) w D:\DocSorter\DocSorter\Merge.cs:wiersz 39
       w DocSorter.MainBox.btnMergeFiles_Click(Object sender, EventArgs e) w D:\DocSorter\DocSorter\MainBox.cs:wiersz 85
       w System.Windows.Forms.Control.OnClick(EventArgs e)
       w System.Windows.Forms.Button.OnClick(EventArgs e)
       w System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
       w System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
       w System.Windows.Forms.Control.WndProc(Message& m)
       w System.Windows.Forms.ButtonBase.WndProc(Message& m)
       w System.Windows.Forms.Button.WndProc(Message& m)
       w System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
       w System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
       w System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
       w System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
       w System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)
       w System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
       w System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
       w System.Windows.Forms.Application.Run(Form mainForm)
       w DocSorter.Program.Main() w D:\DocSorter\DocSorter\Program.cs:wiersz 18
       w System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
       w System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       w Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       w System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       w System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       w System.Threading.ThreadHelper.ThreadStart()
  InnerException: 

2 个答案:

答案 0 :(得分:3)

循环浏览IEnumerable时无法修改它。

由于LINQ to XML使用延迟执行,因此在修改XML时会尝试查找后代。

要解决此问题,您需要在循环之前将元素放在数组中,如下所示:

var results = myDocument.Descendants("myName").ToArray();

foreach (var result in results){
   if (sth...){
      result.replace(myXElement);
   }
}

通过调用ToArray(),您可以强制它立即枚举元素,而不是在循环浏览时找到它们。

答案 1 :(得分:0)

您似乎已经推出了自己的扩展方法replace(myXElement)。但在这种情况下,XNode.ReplaceWith Method (Object)似乎可以满足您的需求。

以下是Microsoft的ReplaceWith(Object)示例,摘自其文档:

==代码==

XElement xmlTree = new XElement("Root",
    new XElement("Child1", "child1 content"),
    new XElement("Child2", "child2 content"),
    new XElement("Child3", "child3 content"),
    new XElement("Child4", "child4 content"),
    new XElement("Child5", "child5 content")
);

XElement child3 = xmlTree.Element("Child3");

child3.ReplaceWith(
    new XElement("NewChild", "new content")
);

Console.WriteLine(xmlTree);

==预期输出==

<Root>
  <Child1>child1 content</Child1>
  <Child2>child2 content</Child2>
  <NewChild>new content</NewChild>
  <Child4>child4 content</Child4>
  <Child5>child5 content</Child5>
</Root>