2010-06-07 204 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>