2010-06-07 158 views
4

Im做这样的事情:替换XML元素

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

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

的问题是,当我替换元素,我不能重复下一个元素的原因有空引用。 (var结果)。

是否有任何其他方式来替换另一个元素,仍然能够遍历该文档?

感谢您的帮助

堆栈跟踪是:

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: 
+1

'VAR的结果= myDocument.Descendants(“myName”);' – SLaks 2010-06-07 21:58:24

+0

什么是调用堆栈的除离子? – SLaks 2010-06-07 21:59:34

+0

我编辑了我的问题,填充了调用堆栈 – gruber 2010-06-07 22:05:53

回答

3

,同时通过它循环,不能修改一个IEnumerable。

由于LINQ to XML使用延迟执行,它试图在修改XML时查找子代。

要解决这个问题,你需要把在数组中的元素通过他们循环之前,就像这样:

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

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

通过调用ToArray(),你强迫它通过元素枚举找到他们为立即代替你通过它们循环。

+0

谢谢,还有一种称为ReplaceNodes()的方法,可能对其他方法有用。 – gruber 2010-06-07 22:21:10

0

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

下面是微软的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>