迭代大型XML文件并复制选择节点

本文关键字:复制 选择 节点 文件 大型 XML 迭代 | 更新日期: 2023-09-27 18:26:17

我需要遍历一个大的XML文件(~2GB),并选择性地将某些节点复制到一个或多个单独的XML文件中。

我的第一个想法是使用XPath迭代匹配的节点,并为每个节点测试节点应该复制到哪个其他文件,如下所示:

var doc = new XPathDocument(@"C:'Some'Path.xml");
var nav = doc.CreateNavigator();
var nodeIter = nav.Select("//NodesOfInterest"); 
while (nodeIter.MoveNext())
{
    foreach (Thing thing in ThingsThatMightGetNodes)
    {
        if (thing.AllowedToHaveNode(nodeIter.Current))
        {
            thing.WorkingXmlDoc.AppendChild(... nodeIter.Current ...);
        }
    }
}

在这个实现中,Thing定义public System.Xml.XmlDocument WorkingXmlDoc来保持它是AllowedToHave()的节点。不过,我不明白如何创建一个新的XmlNode,它是nodeIter.Current.的副本

如果有更好的方法,我也很乐意听到。

迭代大型XML文件并复制选择节点

XPath表达式的求值要求整个XML文档(XMLInfoset)都在RAM中。

对于文本表示超过2GB的XML文件,通常应该有超过10GB的RAM可用于保存XML文档。

因此,虽然并非不可能,但使用另一种技术可能更可取(尤其是在必须具有可快速用于许多请求的资源的服务器上)。

XmlReader(基于类)是适用于此场景的优秀工具。它快速、仅向前,并且不需要在内存中保留读取节点。此外,你的逻辑将保持不变。

您应该考虑LINQ to XML。查看此博客文章了解详细信息和示例:

http://james.newtonking.com/archive/2007/12/11/linq-to-xml-over-large-documents.aspx

尝试一个实现文档投影的XQuery处理器(这是Marion和Simeon首次发布的想法)。它在许多处理器中实现,包括Saxon EE。基本上,如果您运行诸如//x之类的查询,它将过滤输入事件流,并构建一个只包含处理该查询所需信息的树;然后,它将以正常的方式执行查询,但针对一个小得多的树。如果这只是整个文档的一小部分,您可以轻松地将内存需求减少95%左右。