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

问题描述:

我有以下问题:我有非常大的XML文件(如300 +兆),我需要对其进行解析,以他们的一些价值添加到数据库。这些文件的结构也非常复杂。我想用斯塔克斯解析器,因为它提供的拉解析(因而处理)只有XML文件的部分好的可能性的时间,因而不加载在内存中的整个事情,但另一方面与得到的值Stax(至少在这些XML文件上)很麻烦,我需要编写大量的代码。但从后面这一点,将immensly帮助我,如果我能马歇尔XML文件的Java对象(如JAX-B做),但是这会一下子加载整个文件加上一吨的对象实例在内存中。解析非常大的XML文件,并编组为Java对象

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

嗯,首先我要感谢两个人回答我的问题,但我终于结束了不使用这些主张部分是因为这些建议的技术是有点远从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/

+0

很高兴知道您的问题已解决。只是想知道这是如何(在这篇文章中的soln)不同于我发布的内容? – Kashyap

+0

那么,诚实地说,它是大型框架的一部分恐惧,部分懒惰:)(这两者都很糟糕和令人遗憾)。首先,从文档看,EMF看起来像一个相当复杂的框架,它不仅适用于XML处理,还适用于其他许多事情,而且我总是尽可能地避免这种沉重的框架(这只是个人偏好,我不是说一般做不好)。其次,我很懒,而且EMF使用了我不知道的非标准XML解析API,因此我用标准的Java XML API来提供解决方案。 –

+1

事实上,无论您是否喜欢EMF,我都建议不要使用它(“**因为EMF对于这么小的问题**太大了,除非你没有选择。”)。解析器再次引用“so **只是使用任何你想要的**解析,在循环中为每个创建一些StringStream或者**,并传递给JAX-B或EMF。**” – Kashyap

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

无论如何,如果你的XML格式是明确界定,那么一个解决办法是通过愚弄打破整个文件分成几个较小(但仍然良好定义的)XML片段的EMF。然后将每个片段依次加入。我不知道JAX-B,但也许可以在那里应用相同的解决方法。我会推荐这种方法,因为对于这样一个小问题,EMF太大了。

只是为了详细一点,如果你的XML是这样的:

<tag1> 
    <tag2> 
     <tag3/> 
     <tag4> 
      <tag5/> 
     </tag4> 
     <tag6/> 
     <tag7/> 
    </tag2> 

    <tag2> 
     <tag3/> 
     <tag4> 
      <tag5/> 
     </tag4> 
     <tag6/> 
     <tag7/> 
    </tag2> 
............ 
    <tag2> 
     <tag3/> 
     <tag4> 
      <tag5/> 
     </tag4> 
     <tag6/> 
     <tag7/> 
    </tag2> 
</tag1> 

然后,它可以分解成一个XML每个开始<tag2></tag2>结束。而在java中最解析器会接受一个流,所以只使用解析无论你想,在一个循环中创建一些字符串流或东西每个<tag2>,并传递到JAX-B或EMF。

HTH

+0

这事听起来不错,而且我会(在这里它的午夜现在:))尝试明天第一件事。感谢您的建议,听起来很有希望 –

+1

@thekashyap。我可以买一台这样的机器吗?只有一个! –

+0

嘿嘿..那些是我们的测试机器,在家里我和其他人一样在4GB的Win7笔记本电脑上工作.. :) – Kashyap

文件投影可能是这里的答案。 Saxon和其他一些XQuery处理器提供这个选项。如果您有一个合理简单的查询从大型文档中选择少量数据,则查询处理器会分析查询以确定哪些树部分需要用于查询,哪些部分可以在处理期间被丢弃。生成的树通常只能是整个文档大小的1%。对于撒克逊这里详细介绍:

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