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

问题描述:

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

我首先想到的是使用XPath通过匹配节点和哪些其他文件(S)的节点应该被复制到每一个节点测试迭代,像这样:

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

要在2GB XML文档上使用XPath,您的计算机必须具有> 10GB RAM,可能> 16GB。是这样吗? – 2012-02-28 23:57:10

+0

@DimitreNovatchev:是的,我不知道XPath需要这么多的RAM,而且看起来很浪费(这是一个服务器,其他进程肯定会受到影响)。你能提出一个不同的解决方案吗 – 2012-02-29 00:05:52

+0

我推荐使用XmlReader - 因此您不限制RAM。你的逻辑将保持大致相同。 – 2012-02-29 00:12:55

评估XPath表达式需要将整个XML文档(XML Infoset)放在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

+1

LINQ to XML如何用〜2GB输入文件执行? – 2012-02-29 01:11:27

+0

直线上升,可能不是那么好。但是你可以针对流进行操作。请参阅:http://msdn.microsoft.com/en-us/library/system.xml.linq.xstreamingelement.aspx#Y1392。 – 2012-02-29 01:47:41

+0

非常酷! – 2012-02-29 03:01:01

尝试实现文档投影(一个想法首先由马里昂和西蒙出版)的XQuery处理器。它在包括Saxon-EE在内的许多处理器中实施。基本上,如果您运行诸如// x之类的查询,它将过滤输入事件流并构建仅包含处理此查询所需信息的树;它会以正常的方式执行查询,但是会对较小的树进行查询。如果这只是整个文档的一小部分,您可以轻松地将内存需求减少95%左右。