在JAVA中解析大型XML文档

我有以下问题:

我有一个XML文件(大约1GB),并且必须上下迭代(即不顺序;一个接一个),以获得所需的数据并对其进行一些操作。 最初,我使用了DOM Java包,但显然,在解析XML文件时,JVM会达到其最大堆空间并停止。

为了克服这个问题,我提出的解决方案之一是找到另一个迭代XML中每个元素的解析器,然后将它的内容存储在硬盘上的临时SQLite数据库中。 因此,通过这种方式,不会超出JVM的堆,并且一旦填满所有数据,我就会忽略XML文件并继续对临时SQLite数据库执行操作。

还有另一种方法可以解决我的问题吗?

SAX(XML的简单API)将在这里为您提供帮助。

与DOM解析器不同,SAX解析器不会创建XML文档的内存中表示,因此更快并且使用更少的内存。 相反,SAX解析器通过调用回调来通知客户端XML文档结构,即通过调用提供给解析器的org.xml.sax.helpers.DefaultHandler实例上的org.xml.sax.helpers.DefaultHandler

这是一个示例实现:

 SAXParser parser = SAXParserFactory.newInstance().newSAXParser(); DefaultHandler handler = new MyHandler(); parser.parse("file.xml", handler); 

MyHandler您可以定义在生成文档/元素的开始/结束等事件时要采取的操作。

 class MyHandler extends DefaultHandler { @Override public void startDocument() throws SAXException { } @Override public void endDocument() throws SAXException { } @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { } @Override public void endElement(String uri, String localName, String qName) throws SAXException { } // To take specific actions for each chunk of character data (such as // adding the data to a node or buffer, or printing it to a file). @Override public void characters(char ch[], int start, int length) throws SAXException { } } 

如果您不想受内存限制的约束 ,我当然建议您使用当前的方法,并将所有内容存储在数据库中。

解析XML文件应该由SAX parser ,正如每个人都推荐的那样(包括我)。 这样,您可以一次创建一个对象,并且可以立即将其持久保存到数据库中。

对于后处理(解析交叉引用),您可以使用数据库中的SELECT ,生成主键,索引等。如果您对此感到满意,也可以使用ORM(Eclipselink,Hibernate)。

实际上我并不是真的推荐SQLite,它更容易设置MySQL服务器,并将数据存储在那里。 稍后您甚至可以重用XML数据(如果不删除)。

如果你想使用比SAX更高级的方法,这可能是非常棘手的编程,你可以使用最新的Saxon-EE版本来查看流式XSLT转换。 但是,您对于您正在进行的精确处理过于模糊,以了解这是否适用于您的特定情况。

如果你需要一个资源友好的方法来处理非常大的xml,请试试这个: http : //www.xml2java.net/xml-to-java-data-binding-for-big-data/它允许你处理SAX中的数据方式,但具有获得高级事件(xml数据映射到java)的优势,并能够直接在代码中使用这些对象。 所以它结合了jaxb便利性和SAX资源友好性。