解析非常大的XML文件并编组到Java对象

我有以下问题:我有非常大的XML文件(如300+ Megs),我需要解析它们以便将一些值添加到数据库中。 这些文件的结构也非常复杂。 我想使用Stax Parser,因为它提供了一次拉解析(并因此处理)XML文件的一部分的可能性,因此不会将整个内容加载到内存中,但另一方面获取值Stax(至少在这些XML文件上)很麻烦,我需要编写大量代码。 从后一种观点来看,如果我可以将XML文件编组为Java对象(就像JAX-B那样),那将对我有所帮助,但是这会将整个文件加上大量的Object实例同时加载到内存中。

我的问题是,有没有办法按顺序解析(或只是部分解析)文件,然后只将那些部分编组到Java对象中,这样我就可以轻松处理它们而不会让内存陷入困境?

我推荐Eclipse EMF。 但它有同样的问题,如果你给它文件名,它会解析整个事情。 虽然有一些选项可以减少加载的数量,但我没有太多麻烦,因为我们在96 GB RAM的机器上运行。 🙂

无论如何,如果您的XML格式定义得很好,那么一种解决方法是通过将整个文件分解为几个较小(但仍然定义良好)的XML片段来欺骗EMF。 然后一个接一个地提供每个片段。 我不知道JAX-B,但也许可以在那里应用相同的解决方法。 我建议这样做,因为对于这么小的问题,EMF太大了。

如果你的XML看起来像这样,那就详细说明一下:

                 ............          

然后它可以分解为一个XML,每个XML以开头,以结尾。 在java中,大多数解析器都会接受Stream,因此只需使用您想要的任何内容进行解析,为循环中的每个创建一些StringStream或其他内容并传递给JAX-B或EMF。

HTH

好吧,首先我要感谢两个人回答我的问题,但最后我最终没有使用这些命题,部分原因是那些提议的技术与Java有点远,所以说“标准的XML解析”,到目前为止感觉很奇怪。 Java中已经存在类似的工具,部分原因还在于我确实找到了一种只使用Java API来实现这一目标的解决方案。

我不会详细说明我找到的解决方案,因为我已经完成了实现,而且这里放置了很大一部分代码(我使用Spring Batch,有大量的配置和东西) 。

然而,我会对我最终做的事情做一个小评论:

这里的一个重要思想是,如果你有一个XML文档并且它是相应的XSD模式,你可以使用JAXB解析和编组它,你可以用块来完成它,并且可以用一个偶数解析器来读取块,例如STAX然后传递给JAXB Marshaller。

这实际上意味着你必须首先确定你的XML文件中哪里是一个好地方你可以说“这部分有很多重复结构,我会一次一个地处理这些重复”。 那些重复的部分通常是在父标记内重复的相同(子)标记。 因此,您所要做的就是在STAX解析器中创建一个在每个子标记的开头触发的事件侦听器,而不是将该子标记的内容流式传输到JAXB,并使用JAXB对其进行编组并对其进行处理。

实际上这个想法在本文中得到了很好的描述,我遵循了这一点(真的,它是从2006年开始的,但它处理的是当时非常新的JDK 1.6,因此版本方面根本不是那么老):

http://www.javarants.com/2006/04/30/simple-and-efficient-xml-parsing-using-jaxb-2-0/

文档投影可能就是答案。 Saxon和许多其他XQuery处理器都提供此选项。 如果您有一个相当简单的查询从大型文档中选择少量数据,查询处理器会分析查询以确定查询可以使用树的哪些部分,以及在处理期间可以丢弃哪些部分。 生成的树通常只能是完整文档大小的1%。 撒克逊人的详细资料:

http://saxonica.com/documentation/sourcedocs/projection.xml