替换 xml 元素

发布于 2024-09-04 10:24:26 字数 2810 浏览 2 评论 0原文

我正在做类似的事情:

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

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

问题是,当我替换一个元素时,我无法迭代到下一个元素,因为存在空引用。 (结果中的变量结果)。

是否有其他方法可以将该元素替换为另一个元素,并且仍然能够迭代该文档?

感谢您的帮助,

堆栈跟踪是:

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: 

Im doing something like that:

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

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

The problem is that when I replace an element I cant iterate to the next element cause there is null reference. (var result in results).

Is there any other way to replace that element with another one and still be able to iterate through that document ?

thanks for help

the stacktrace is:

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: 

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

毁虫ゝ 2024-09-11 10:24:26

循环访问 IEnumerable 时无法对其进行修改。

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

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

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

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

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

You cannot modify an IEnumerable while looping through it.

Since LINQ to XML uses deferred execution, it's trying to find the descendants as you modify the XML.

To fix this, you need to put the elements in an array before looping through them, like this:

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

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

By calling ToArray(), you force it to enumerate through the elements immediately instead of finding them as you loop through them.

烙印 2024-09-11 10:24:26

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

以下是 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>

It appears you have rolled your own Extension Method replace(myXElement). But it seems that XNode.ReplaceWith Method (Object) would serve your need in this situation.

Here's Microsoft's example for ReplaceWith(Object) taken from its documentation:

== Code ==

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);

== Expected Output ==

<Root>
  <Child1>child1 content</Child1>
  <Child2>child2 content</Child2>
  <NewChild>new content</NewChild>
  <Child4>child4 content</Child4>
  <Child5>child5 content</Child5>
</Root>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文