2011-12-22 53 views
1

我試圖在通過候選節點集迭代時通過從其中刪除節點來修改XmlDocument。我遇到的問題是,即使節點有206個元素,MoveNext()在元素1之後返回false。在使用XPathNodeIterator遍歷XmlDocument時修改XmlDocument

這是因爲我正在修改數據嗎?我怎樣才能解決這個問題?還是有其他原因我錯過了?我的代碼如下。

完成同樣事情的任何其他方式(有選擇地從XML文件中刪除節點)也可以正常工作。

XmlReader reader = XmlReader.Create(myFile.FullName); 

// Load document 
XmlDocument document = new XmlDocument(); 
document.Load(reader); 
XPathNavigator navigator = document.CreateNavigator(); 

// Select elementD nodes with the correct format (there are other elementD nodes that we 
// want to ignore 
XPathNodeIterator nodes = navigator.Select("/elementA/elementB/elementC/elementB/elementD"); 

// Keep count of how many nodes we've deleted 
int count = 0; 

while (nodes.MoveNext) 
{ 
moreNodes = nodes.MoveNext(); 

XPathNavigator node = nodes.Current; 

logger.log(node.ToString()); 
string name = node.GetAttribute("name", ""); 

// If name isn't a valid name, delete it from the document 
if (!validNames.Contains(name)) 
{ 
    count++; 

    // Get the parent node (elementB) 
    XPathNavigator elementBNode = node.SelectSingleNode(".."); 

    // And its parent node (elementC) 
    XPathNavigator elementCNode = elementBNode.SelectSingleNode(".."); 

    // Delete the elementB node 
    elementBNode.DeleteSelf(); 

    // It the elementC node is empty, then delete it as well 
    if (!elementCNode.HasChildren) 
    { 
    elementCNode.DeleteSelf(); 
    } 
} 
} 

// Make sure the document gets formatted nicely 
XmlWriterSettings settings= new XmlWriterSettings(); 
settings.Indent = true; 
settings.IndentChars = (" "); 

// Write out the modified document 
XmlWriter writer = XmlWriter.Create(myFile + ".modified", settings); 
document.WriteTo(writer); 

回答

2

documentation here(下「備註」):

當使用XPathNodeIterator,如果編輯當前節點或其祖先的任何 ,您目前的位置丟失。如果要編輯已選擇的節點數 ,請創建XPathNavigator陣列, 將XPathNodeIterator中的所有節點複製到陣列中,然後 迭代整個陣列並修改節點。

+0

好吧,現在我覺得很蠢。我衝過那頁,完全錯過了那部分。像魅力一樣工作,謝謝。 –

0

這裏是一個克隆要刪除元素的代碼示例。

 XPathNodeIterator iteratorRef = nav.Select(path, namespaceManager); 
     List<XPathNavigator> toDelete = new List<XPathNavigator>(); 

     while (iteratorRef.MoveNext()) 
     { 
      bool condition = IsElementToDelete(iteratorRef); 
      if (condition) 
      { 
       // It is important to clone Current otherwise you'll sameelement in toDelete 
       toDelete.Add(iteratorRef.Current.Clone()); 
      } 
     } 
     foreach (XPathNavigator xPathNavigator in toDelete) 
     { 
      xPathNavigator.DeleteSelf(); 
     }