如何最好地在.NET中使用XPath和非常大的XML文件?
我需要在C#中对相当大的XML文件(这里可能超过一千兆字节)进行一些处理,包括执行一些复杂的xpath查询。 我遇到的问题是我通常通过System.XML库执行此操作的标准方法是在将任何内容添加到内存之前将整个文件加载到内存中,这会导致此大小的文件出现内存问题。
我只需要阅读它们并查询其中包含的数据就不需要更新文件。 一些XPath查询非常复杂,并且涉及多个级别的父子类型关系 – 我不确定这是否会影响使用流式读取器的能力,而不是将数据作为块加载到内存中。
我可以看到使其工作的一种方法是使用基于流的方法执行简单分析,并且可能将XPath语句包装到XSLT转换中,之后我可以在文件中运行,尽管看起来有点复杂。
或者我知道XPath查询有一些元素不能运行,所以我想我可以根据它的原始树结构将文档分解为一系列较小的片段,这可能足够小,可以在内存中处理造成太大的破坏。
我试图在这里解释我的目标,所以如果我在一般方法上咆哮完全错误的树,我相信大家可以让我正确…
XPathReader就是答案。 它不是C#运行时的一部分,但可以从Microsoft下载。 这是一篇MSDN文章 。
如果使用XmlTextReader构造XPathReader,则可以使用XPath表达式方便地获得流式读取的效率。
我没有在千兆字节大小的文件上使用它,但我已经在数十兆字节的文件上使用它,这通常足以减慢基于DOM的解决方案。
引用如下:“XPathReader提供了以流方式对XML文档执行XPath的能力”。
从Microsoft下载
技嘉XML文件! 我不羡慕你这个任务。
有没有办法以更好的方式发送文件? 例如,它们是通过网络发送给您的 – 如果它们是更有效的格式可能对所有相关人员更好。 将文件读入数据库并不是一个坏主意,但确实非常耗时。
我不会尝试通过读取整个文件在内存中完成所有操作 – 除非你有64位操作系统和大量内存。 如果文件变成2,3,4GB怎么办?
另一种方法可能是读取XML文件并使用SAX解析文件并根据某些逻辑拆分写出较小的XML文件。 然后,您可以使用XPath处理这些 。 我在20-30MB文件上使用了XPath,速度非常快。 我原本打算使用SAX,但我想我会给XPath一个机会,并且很惊讶它有多快。 我节省了大量的开发时间,每个查询可能只丢失250毫秒。 我使用Java进行解析,但我怀疑.NET中没有什么区别。
我确实读过XML :: Twig(Perl CPAN模块)是为了处理基于SAX的XPath解析而明确编写的。 你能用其他语言吗?
这也可以帮助https://web.archive.org/web/1/http://articles.techrepublic%2ecom%2ecom/5100-10878_11-1044772.html
你已经概述了你的选择。
您需要放弃XPath并使用XmlTextReader,或者您需要将文档分解为可以使用XPath的可管理块。
如果你选择后者使用XPathDocument,它的readonly限制允许更好地使用内存。
为了使用标准.NET类执行XPath查询,需要将整个文档树加载到内存中,如果它可能需要高达一千兆字节,这可能不是一个好主意。 恕我直言, XmlReader是一个很好的类来处理这样的任务。
您似乎已经尝试使用 XPathDocument
并且无法在内存中容纳已解析的xml文档 。
如果是这种情况,在开始拆分文件之前(这最终是正确的决定!)您可以尝试使用Saxon XSLT / XQuery处理器。 它具有非常有效的内存表示forms的加载XML文档( “tinytree”模型 )。 此外, Saxon SA (shema-aware版本,不是免费的)有一些流媒体扩展 。 在这里阅读更多相关信息。
如何将整个内容读入数据库,然后使用临时数据库? 这可能会更好,因为使用TSQL可以更有效地完成查询。
我认为最好的解决方案是创建自己的xml解析器,它可以读取小块而不是整个文件,或者你可以将大文件拆分成小文件并使用这些文件的dotnet类。 问题是你无法解析一些数据,直到整个数据可用为止所以我建议使用你自己的解析器而不是dotnet类
你有没有尝试过XPathDocument? 此类已针对有效处理XPath查询进行了优化。
如果使用XPathDocument无法有效处理输入文档,则可以考虑使用XmlReader预处理和/或拆分输入文档。
因为在您的情况下,数据大小可以在Gbs中运行,您是否考虑过将ADO.NET与XML一起用作数据库。 除此之外,内存占用量不会很大。
另一种方法是使用Linq to XML和XElementStream之类的元素。 希望这可以帮助。