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

まったく同じスタックトレースを表示するJava1.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;
            }
        }
    }
}

これはJava5で機能しますが、Java6でOOMを取得します。

私はそれを次のように実行します:

java -DentityExpansLimit=512000 -jar xmltest.jar

そしてそれは印刷します:

Incollections = 8353

どちらが便利ですか:

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

したがって、参考までに、データポイントなど。

于 2009-02-03T22:43:22.917 に答える
0

&eacute;コード内のHTMLエンティティ、つまり最初のブロックの「Jos」に問題があるようです。少なくとも私のブラウザは、ファイルを開いたときに問題があることを通知XMLEntityScannerし、スタックトレースに表示されます。私はXMLの専門家ではありませんが、HTMLエンティティが実際には一般的にXML用に定義されていない可能性がありますか?

うんを編集、それだけです。ウィキペディアによると、のようなエンティティ&eacute;はHTMLDTDで定義されています。XMLには、非常に少数の事前定義されたエンティティしかありません。

于 2009-02-03T21:22:23.360 に答える
0

これに対する正しい用語はわかりませんが、XML はどの程度「深く」なっているでしょうか。たとえば、例の「作成者」タグは 2 要素の深さです。非常に深いタグを使用している場合、それが原因でメモリの問題が発生している可能性があります。

于 2009-02-03T21:43:56.797 に答える
0

XML ファイル内のテキスト セグメント (または CDATA、処理命令、またはコメント) の 1 つが非常に長く、パーサーがそれを複数のセグメントに分割していないようです。または、パーサーが DOCTYPE 宣言を適切に解析できない可能性があります。その場合、DTD サブセットの一部であるかのように、すべての xml コンテンツを読み取ろうとする可能性があります。

しかし、それは単なる憶測です。Stax を試したことがあるとおっしゃいましたが、どの実装ですか? JDK 1.6 には Sun Sjsxp が付属しています。しかし、Woodstox ( http://woodstox.codehaus.org ) を試すこともできます。Woodstox は、より堅牢な方法で物事を処理することがよくあります。したがって、Woodstox を使用していない場合は、何が起こるかを確認できます。テキスト合体を強制しない限り、テキスト セグメントを小さなチャンクに分割します (デフォルトではありません)。

念のため、Stax リファレンス実装 ( http://stax.codehaus.org ) を使用してテストしていました。残念ながら、非常にバグが多いことが知られています。そのため、問題が発生する可能性があります。Sjsxp と Woodstox はどちらも、Stax でのより良い選択です。

于 2009-03-31T18:27:20.240 に答える