5

Big XML File的后续问题:

首先非常感谢您的回答。之后……我做错了什么?这是我使用 SAX 的课程:

public class SAXParserXML extends DefaultHandler {
  public static void ParcourXML() {

      DefaultHandler handler = new SAXParserXML();
      SAXParserFactory factory = SAXParserFactory.newInstance();
      try {
          String URI = "dblp.xml";
          SAXParser saxParser = factory.newSAXParser();
          saxParser.parse(URI,handler);
      } catch (Throwable t) {
     t.printStackTrace ();
       }
  }



  public void startElement (String namespaceURI,String simpleName,String qualifiedName,Attributes attrs) throws SAXException {
  }
  public void endElement (String namespaceURI,String simpleName,String qualifiedName) throws SAXException {

  }
}

你可以看到我对我的 XML 文件没有做任何事情,但它给出了这个错误:

java.lang.OutOfMemoryError: Java heap space
    at com.sun.org.apache.xerces.internal.util.XMLStringBuffer.append(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.refresh(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLEntityScanner.invokeListeners(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLEntityScanner.peekChar(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(Unknown Source)
    at javax.xml.parsers.SAXParser.parse(Unknown Source)
    at javax.xml.parsers.SAXParser.parse(Unknown Source)
    at SAXParserXML.ParcourXML(SAXParserXML.java:30)
    at Main.main(Main.java:28)

我也尝试了 Stax……同样的错误……我该怎么办?我还将 Java 堆大小增加到 1260M

java -Xmx1260M SAXParserXML

XML 文件具有以下形式:

<dblp> 
   <incollection> 
      <author>... </author> 
      .... 
      <author>... </author> 
      #other tags-i'm interested only by <author>#
      ... 
   </incollection> 
   <incollection> 
   # the same thing# 
   </incollection> 
   .... 
</dblp> 

您可以找到原始文件:http ://dblp.uni-trier.de/xml/

谢谢

4

5 回答 5

6

Java 1.6有一个错误,它显示了完全相同的堆栈跟踪,目前尚未修复。较新的 Xerces 版本似乎没问题。

对于这么大的文档,仍然包含大量结构,您可以考虑使用拉解析,即解析部分结构,例如使用StAX

于 2009-02-03T21:22:16.700 回答
2

好吧,给定:

public class Main {

    /**
     * @param args the command line arguments
     */
    public static void main(String argv[]) {
        Writer out;

        // Use an instance of ourselves as the SAX event handler
        Echo handler = new Echo();
        // Use the default (non-validating) parser
        SAXParserFactory factory = SAXParserFactory.newInstance();
        try {
            // Set up output stream
            out = new OutputStreamWriter(System.out, "UTF8");
            // Parse the input 
            SAXParser saxParser = factory.newSAXParser();
            saxParser.parse(new File("/tmp/dblp.xml"), handler);
        } catch (Throwable t) {
            t.printStackTrace();
        }
        System.out.println("Incollections = " + handler.cnt);
        System.exit(0);
    }

    static class Echo extends DefaultHandler {
        public int cnt = 0;
        @Override
        public void startElement(String namespaceURI,
                String sName, // simple name
                String qName, // qualified name
                Attributes attrs)
                throws SAXException {
            if (qName.equals("incollection")) {
                cnt = cnt + 1;
            }
        }
    }
}

这在 Java 5 下对我有用,但在 Java 6 下我确实得到了 OOM。

我这样运行它:

java -DentityExpansLimit=512000 -jar xmltest.jar

它打印:

Incollections = 8353

哪个方便:

grep "<incollection" /tmp/dblp.xml | wc -l
8353

所以,仅供参考,数据点等。

于 2009-02-03T22:43:22.917 回答
0

您的代码中的 HTML 实体似乎存在问题,即&eacute;第一个块中的“Jos”。至少我的浏览器在我打开文件时告诉我它有问题,并XMLEntityScanner显示在堆栈跟踪中。我不是 XML 专家,但实际上 HTML 实体是否通常不是为 XML 定义的?

编辑是的,就是这样。根据Wikipedia&eacute; , HTML DTD 中定义了类似的实体;XML 只有极少数的预定义实体。

于 2009-02-03T21:22:23.360 回答
0

我不知道正确的术语,但是您的 XML 有多“深”?例如,您示例中的“作者”标签深度为 2 个元素。如果您的标签非常深,也许这就是您遇到内存问题的原因?

于 2009-02-03T21:43:56.797 回答
0

听起来XML文件中的文本段(或CDATA、处理指令或注释)之一很长,解析器不会将其拆分为多个段。或者可能是解析器无法正确解析 DOCTYPE 声明:如果是这样,它可能会尝试读取所有 xml 内容,就好像它是 DTD 子集的一部分一样。

但这只是猜测。您提到您已经尝试过 Stax:哪个实现?JDK 1.6 随 Sun Sjsxp 一起提供。但是您也可以尝试 Woodstox ( http://woodstox.codehaus.org ),它通常以更强大的方式处理事情。因此,如果您不使用 Woodstox,您可以看到会发生什么。除非您强制文本合并(非默认),否则它会将文本段拆分为更小的块。

哦,以防万一您使用 Stax 参考实现(http://stax.codehaus.org)进行测试;不幸的是,它很容易出错。所以这可能会导致问题。Sjsxp 和 Woodstox 都是 Stax 的更好选择。

于 2009-03-31T18:27:20.240 回答