我需要遍历一个大型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的副本。
如果有更好的方法,我也很乐意听到它。
答案 0 :(得分:3)
评估XPath表达式要求整个XML文档(XML Infoset)在RAM中。
对于文本表示超过2GB的XML文件,通常只有10GB以上的RAM可用于存放XML文档。
因此,虽然并非不可能,但可能更喜欢使用其他技术(特别是在必须拥有快速可用于许多请求的资源的服务器上)。
XmlReader(基于类)是此方案的绝佳工具。它只是快速,仅向前,并且不需要将读取节点保留在存储器中。此外,您的逻辑将保持几乎相同。
答案 1 :(得分:1)
您应该考虑使用LINQ to XML。查看此博客文章了解详细信息和示例:
http://james.newtonking.com/archive/2007/12/11/linq-to-xml-over-large-documents.aspx
答案 2 :(得分:0)
尝试实现文档投影的XQuery处理器(Marion和Simeon首先发布的一个想法)。它在许多处理器中实现,包括Saxon-EE。基本上,如果运行诸如// x的查询,它将过滤输入事件流并构建一个仅包含处理此查询所需信息的树;然后它将以正常方式执行查询,但是针对更小的树。如果这只是整个文档的一小部分,您可以轻松地将内存需求减少95%左右。