2009-02-03 6 views
5

Followup question to Big XML File:RE: Big XML file

Primo, grazie mille per le vostre risposte. Dopo ... cosa faccio di sbagliato? Questa è la mia classe che usa 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 { 

    } 
} 

Si può vedere che non faccio niente con il mio file XML ma dà questo errore:

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) 

ho provato anche Stax ... lo stesso errore ... che cosa posso fare? Inoltre ho aumentato la Java heap dimensione fino a 1260m

java -Xmx1260M SAXParserXML 

il file XML ha questa forma:

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

È possibile trovare il file originale: http://dblp.uni-trier.de/xml/

Grazie

+0

Sarebbe di grande aiuto se ci dicessi di più sul tipo di XML che stai analizzando. –

risposta

6

C'è a bug per Java 1.6 che mostra la stessa identica traccia di stack, ed è ora non fissato. Le versioni più recenti di Xerces sembrano andare bene.

Per i documenti così grandi, che contengono ancora una buona quantità di struttura, è possibile pensare di utilizzare l'analisi pull, ovvero l'analisi di strutture parziali, ad esempio con StAX.

+0

Ho già provato Stax ... dà lo stesso errore – user61652

+0

Se fornisce la stessa traccia di stack, non stai usando StAX. Qual è la traccia dello stack per StAX? – lavinio

+0

Penso di avere lo stesso problema dell'inizio dell'argomento. La pagina bug afferma che il bug è chiuso ... Ma è davvero risolto? Sto usando JDK 6 Update 23 su Windows XP. –

0

Sembra esserci un problema con le entrate HTML nel codice, ovvero "Jos &eacute;" nel primo blocco. Almeno il mio browser mi dice che c'è un problema quando apro il file, e XMLEntityScanner si presenta nella traccia dello stack. Non sono un esperto di XML, ma potrebbe essere che le entità HTML non siano in realtà definite per XML in generale?

Modifica Sì, è tutto. Secondo Wikipedia, entità come &eacute; sono definite nella DTD HTML; XML ha solo un numero molto piccolo di entità predefinite.

+0

Tutte le entità sono definite in dblp.dtd – user61652

+0

Ma ciò causerebbe un errore di memoria? Neanche io sono un esperto di XML, ma penserei che le entità cattive come é causerebbero SAXExceptions in opposizione alle eccezioni di memoria. – Michael

+0

Questa risposta non è di alcun beneficio per questa domanda ... – mark

0

Non conosco la terminologia corretta per questo, ma quanto "profondo" è il tuo XML andare? Ad esempio, il tag "author" nel tuo esempio è profondo 2 elementi. Se hai tag che sono davvero molto profondi, forse è per questo che stai avendo problemi di memoria?

+0

il livello più profondo è 2 – user61652

+0

L'annidamento in realtà non dovrebbe avere importanza: la quantità di memoria utilizzata per livello è molto piccola per SAX e Stax. Voglio dire, non a meno che non siano decine di migliaia di livelli o giù di lì. :) – StaxMan

2

Beh, dato:

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

Questo funziona per me sotto Java 5, ma si ottiene l'OOM sotto Java 6.

corro in questo modo:

java -DentityExpansLimit=512000 -jar xmltest.jar 

E stampa:

Incollections = 8353 

Che è conveniente:

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

Quindi, FYI, punto dati, ecc.

+0

Grazie mille ... Questo era il problema, dovevo compilare con Java 5 ed estendere il limite di entità: Java -DentityExpansionLimit = 512000 Principale – user61652

0

Sembra che uno dei segmenti di testo (o CDATA, istruzione di elaborazione o commento) nel file XML sia molto lungo e il parser non lo divida in più segmenti. Oppure il parser non riesce ad analizzare correttamente la dichiarazione DOCTYPE: in tal caso, potrebbe provare a leggere tutto il contenuto xml come se fosse parte del sottoinsieme DTD.

Ma questa è solo speculazione. Hai detto che hai provato Stax: quale implementazione? JDK 1.6 viene fornito con Sun Sjsxp. Ma potresti anche provare Woodstox (http://woodstox.codehaus.org), che spesso gestisce le cose in modo un po 'più robusto. Quindi, se non usi Woodstox, puoi vedere cosa succede. Divide i segmenti di testo in blocchi più piccoli a meno che non si imposti il ​​raggruppamento del testo (non predefinito).

Oh e nel caso si stessero testando utilizzando l'implementazione di riferimento Stax (http://stax.codehaus.org); purtroppo è noto per essere molto buggy. Quindi ciò potrebbe causare problemi. Sia Sjsxp che Woodstox sono scelte molto migliori con Stax.