2009-02-03 5 views
5

Followup Frage zu Big XML File:RE: Big XML-Datei

Zunächst vielen Dank für eure Antworten. Nach ... was mache ich falsch? Das ist meine Klasse, die SAX verwendet:

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 { 

    } 
} 

können Sie sehen, dass ich nichts mit meiner XML-Datei zu tun, aber es gibt diesen Fehler:

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) 

Ich habe auch versucht Stax ... den gleichen Fehler ... was Kann ich tun? Auch ich die Java Heap-Größe bis

java -Xmx1260M SAXParserXML 

die XML-Datei hat dieses Formular 1260m erhöht:

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

können Sie die Original-Datei finden: http://dblp.uni-trier.de/xml/

Dank

+0

Es würde helfen, wenn Sie uns mehr darüber erzählen, welche Art von XML Sie analysieren. –

Antwort

6

Es gibt eine bug für Java 1.6, die genau die gleiche Stack-Trace zeigt, und es ist jetzt unfixiert. Neuere Xerces-Versionen scheinen in Ordnung zu sein.

Für Dokumente so groß, die immer noch eine ziemlich große Struktur enthalten, könnten Sie darüber nachdenken, Pull-Parsing zu verwenden, d.h. Parsing von Teilstrukturen, zum Beispiel mit StAX.

+0

Ich habe bereits versucht Stax ... es gibt den gleichen Fehler – user61652

+0

Wenn es die gleiche Stack-Trace gibt, verwenden Sie nicht StAX. Was ist der Stack-Trace für StAX? – lavinio

+0

Ich denke ich habe das selbe Problem wie der Starter. Die Bug-Seite besagt, dass der Bug geschlossen ist ... Aber ist es wirklich behoben? Ich verwende JDK 6 Update 23 unter Windows XP. –

0

Es scheint ein Problem mit HTML-Enites in Ihrem Code, nämlich "Jos &eacute;" im ersten Block. Zumindest mein Browser sagt mir, dass es ein Problem damit gibt, wenn ich die Datei öffne, und XMLEntityScanner erscheint im Stack-Trace. Ich bin kein XML-Experte, aber könnte es sein, dass HTML-Entitäten für XML im Allgemeinen nicht definiert sind?

Bearbeiten Yup, das ist es. Nach Wikipedia sind Entitäten wie &eacute; in der HTML-DTD definiert; XML hat nur eine sehr kleine Anzahl vordefinierter Entitäten.

+0

Alle Entitäten sind in dblp.dtd definiert – user61652

+0

Aber würde das einen Speicherfehler verursachen? Ich bin auch kein XML-Experte, aber ich würde denken, dass schlechte Entitäten wie SA SAXExceptions im Gegensatz zu Speicherausnahmen verursachen würden. – Michael

+0

Diese Antwort ist überhaupt nicht von Vorteil für diese Frage ... – mark

0

Ich weiß nicht die richtige Terminologie dafür, aber wie "tief" geht Ihr XML? Zum Beispiel ist das "author" -Tag in Ihrem Beispiel 2 Elemente tief. Wenn Sie Tags haben, die wirklich sehr tief sind, haben Sie vielleicht deshalb Speicherprobleme?

+0

die tiefste Ebene ist 2 – user61652

+0

Verschachtelung sollte eigentlich nicht wichtig sein: Menge an Speicher pro Ebene ist sehr klein für SAX und Stax. Ich meine, nicht, es sei denn, es sind Zehntausende von Leveln oder so. :) – StaxMan

2

Nun, gegeben:

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; 
      } 
     } 
    } 
} 

Dies funktioniert für mich unter Java 5, aber ich bekomme die OOM unter Java 6.

ich es wie folgt aus:

java -DentityExpansLimit=512000 -jar xmltest.jar 

Und es druckt:

Incollections = 8353 

Was ist praktisch:

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

Also, FYI, Datenpunkt usw.

+0

Vielen Dank ... Das war das Problem, ich sollte mit Java 5 kompilieren und das Entity-Limit erweitern: Java -DentityExpansionLimit = 512000 Main – user61652

0

Es klingt wie eines der Textsegmente (oder CDATA, Verarbeitungsanweisung oder Kommentar) in XML-Datei ist sehr lang, und Parser teilt es nicht in mehrere Segmente. Oder es könnte sein, dass der Parser die DOCTYPE-Deklaration nicht richtig analysiert: Wenn ja, könnte es versuchen, den gesamten XML-Inhalt so zu lesen, als ob er Teil der DTD-Teilmenge wäre.

Aber das ist nur Spekulation. Sie haben erwähnt, dass Sie Stax ausprobiert haben: welche Implementierung? JDK 1.6 kommt mit Sun Sjsxp. Aber Sie könnten auch versuchen, Woodstox (http://woodstox.codehaus.org), die oft Dinge in etwas robuster Weise behandelt. Wenn Sie also Woodstox nicht verwenden, können Sie sehen, was passiert. Es teilt Textsegmente in kleinere Abschnitte auf, es sei denn, Sie erzwingen das Zusammenführen von Text (nicht Standard).

Oh und nur für den Fall, dass Sie mit Stax Referenzimplementierung getestet wurden (http://stax.codehaus.org); Es ist leider bekannt, dass es sehr buggy ist. Das könnte Probleme verursachen. Beide Sjsxp und Woodstox sind viel bessere Entscheidungen mit Stax.