在Java中解析大型XML响应

问题描述

| 我有一个Java程序,它向我没有修改能力的Web服务发出请求。如果我尝试将其解析为Document对象,则其中一个请求的响应可能会非常大,以至堆耗尽了内存。为了解决这个问题,我将响应逐块读取到byte []缓冲区中,并将其写入磁盘。然后,我计划逐行扫描文件,并从找到的每个元素中构建Document对象(这些是响应中唯一需要的元素):
StringBuilder sb = null;
String line = null;

while( (line = reader.readLine()) != null ){
    if(line.trim().equals(\"<bond>\")){
        sb = new StringBuilder(line);
    }
    else if(line.trim().equals(\"</bond>\")){
        Document doc = builder.parse(sb.toString());
        // Process doc
    }
    else{
        sb.append(line);
    }
}
不幸的是,似乎换行符在响应中转换为空格,因此所有内容都是一条巨大的行。我正在考虑的一种解决方案是使用SAX进行解析,并以相同的方式构建我的Document片段。有人有其他解决方案吗?还是我最好的选择? 谢谢, 杰瑞德     

解决方法

        如果您想使用SAX或DOM解析器,则SAX解析器可能是您最好的选择。它不将xml存储在内存中,因此它将能够处理较大的XML文件。     ,        有多种用于在Java中解析XML文档的API。您似乎正在使用DOM API。它读取整个XML文档并将其转换为节点树。您将获得一个包含所有这些节点的“ 1”对象。 DOM API的优点是它相当容易使用,但是缺点是,如您所注意到的,如果XML很大,所有这些节点都将占用大量内存。 还有SAX API,它们的工作方式有所不同。这通过回调机制起作用:您告诉XML解析器,只要它在XML文件中遇到开始或结束标记或数据时就被调用。然后,您可以在回调方法中确定要执行的操作,并且仅存储所需的数据。这样做的好处是可以扩展到大型文档,因为整个XML树不需要驻留在内存中。缺点是该API级别较低,使用起来比较麻烦。 还有StAX,其目的是介于DOM和SAX API之间。 如果您需要处理大型XML文档,则最好使用SAX或StAX API而不是DOM API。     ,        如果响应很大,是的,SAX解析器将是合适的,否则创建DOM结构时,您将再次耗尽内存。 我还可以推荐Smooks框架,用于将XML转换为其他形式。它非常适合处理非常大的数据集,并且在(http://www.smooks.org)中内置了许多东西。 Smooks允许您指定XML结构的哪些部分用于生成新的Java对象,XML或其他东西。     ,        我认为使用SAXBuilder和XPath可能比while循环更好。 这些线上的东西-
Document doc = new SAXBuilder().build(new StringReader(xmlStr));
XPath xPath = XPath.newInstance(\"/*/YourElement\");
Element ele = xPath.selectSingleNode(doc);
ele.getChild(\"ChildElement\");
    ,        您可以看一下诸如Nux之类的库,该库使您可以将XML流与XPath结合起来以仅提取所需的值。可能值得研究而不是尝试编写自定义内容。     ,        如果堆大小有问题,可以尝试使用以下选项增加堆大小: java -Xms64m -Xmx256m 这将使您的初始堆大小为64MB,最大为256MB。您可以使用其他值。这样的优点是不需要任何代码更改。