在使用XPathNodeIterator遍历XmlDocument时修改它

本文关键字:修改 XmlDocument 遍历 XPathNodeIterator | 更新日期: 2023-09-27 18:18:34

我试图通过删除节点来修改XmlDocument,而我正在迭代候选节点集。我遇到的问题是,即使节点有206个元素,MoveNext()在元素1之后返回false。

这可能是因为我正在修改数据吗?我怎么才能避开这个问题呢?还是我失踪还有别的原因?我的代码如下:

任何其他方式完成同样的事情(有选择地从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);

在使用XPathNodeIterator遍历XmlDocument时修改它

从这里的文档(在"备注"下):

使用XPathNodeIterator时,如果编辑当前节点或任何在它的祖先中,你现在的位置已经丢失了。如果您想编辑您所选择的节点数,创建XPathNavigator数组,然后,将XPathNodeIterator中的所有节点复制到数组中遍历数组并修改节点。

下面是克隆要删除的元素的代码示例。

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