【问题标题】:Modifying XmlDocument while iterating through it with XPathNodeIterator在使用 XPathNodeIterator 迭代时修改 XmlDocument
【发布时间】:2011-12-22 22:55:53
【问题描述】:

我正在尝试通过在迭代候选节点集时从中删除节点来修改 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);

【问题讨论】:

    标签: c# xml xpath iterator


    【解决方案1】:

    来自documentation here(在“备注”下):

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

    【讨论】:

    • 好吧,现在我觉得自己很愚蠢。我浏览了该页面并完全错过了那部分。工作就像一个魅力,谢谢。
    【解决方案2】:

    这里是克隆要删除的元素的代码示例。

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

    【讨论】:

      猜你喜欢
      • 2021-11-28
      • 2013-05-13
      • 2014-09-17
      • 2016-03-26
      • 2017-12-05
      • 2018-10-12
      • 1970-01-01
      • 2012-12-08
      • 2017-09-25
      相关资源
      最近更新 更多