在JAVA中解析大型XML文档

时间:2013-02-28 09:53:01

标签: java xml sqlite xml-parsing

我有以下问题:

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

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

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

4 个答案:

答案 0 :(得分:12)

SAX (Simple API for XML)会帮助你。

  

与DOM解析器不同,SAX解析器不会创建内存   XML文档的表示,因此更快,使用更少   记忆。相反,SAX解析器通知客户端XML文档   通过调用回调来实现结构,即通过调用a上的方法   提供给解析器的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 {
    }

}

答案 1 :(得分:3)

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

解析XML文件应该由SAX parser完成,正如大家所建议的那样(包括我)。这样,您可以一次创建一个对象,并且可以立即将其保存到数据库中。

对于后处理(解析交叉引用),您可以使用数据库中的SELECT,制作主键,索引等。如果您觉得可以使用ORM(Eclipselink,Hibernate)对此很满意。

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

答案 2 :(得分:1)

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

答案 3 :(得分:0)

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