2009-02-03 17 views
5

Pregunta de seguimiento a Big XML File:RE: archivo XML grande

Primero muchas gracias por las respuestas. Después de ... lo que hago mal? Esta es mi clase que utiliza 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 { 

    } 
} 

Se puede ver que no hago nada con mi archivo XML pero da este error:

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) 

me trataron también Stax ... el mismo error ... lo ¿puedo? También he aumentado el montón de Java tamaño de hasta 1260m

java -Xmx1260M SAXParserXML 

el archivo XML tiene esta forma:

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

se puede encontrar el archivo original: http://dblp.uni-trier.de/xml/

Gracias

+0

Sería útil que nos diga más sobre el tipo de XML que está analizando. –

Respuesta

6

Hay de a bug para Java 1.6 que muestra exactamente la misma traza de la pila, y está sin fijar a partir de ahora. Las versiones más nuevas de Xerces parecen estar bien.

Para documentos tan grandes, que aún contienen una buena cantidad de estructura, podría pensar en utilizar el análisis de extracción, es decir, el análisis de estructuras parciales, por ejemplo, con StAX.

+0

Ya he probado Stax ... da el mismo error – user61652

+0

Si le da el mismo seguimiento de pila, no está usando StAX. ¿Cuál es el seguimiento de pila para StAX? – lavinio

+0

Creo que tengo el mismo problema que el tema principal. La página de errores indica que el error está cerrado ... ¿Pero realmente está arreglado? Estoy usando la actualización 23 de JDK 6 en Windows XP. –

0

Parece que hay un problema con las entidades HTML en su código, es decir, "Jos &eacute;" en el primer bloque. Al menos, mi navegador me dice que hay un problema cuando abro el archivo y aparece XMLEntityScanner en el seguimiento de la pila. No soy un experto en XML, pero ¿podría ser que las entidades HTML en realidad no están definidas para XML en general?

Editar Sí, eso es todo. De acuerdo con Wikipedia, las entidades como &eacute; se definen en el HTML DTD; XML tiene solo un número muy pequeño de entidades predefinidas.

+0

Todas las entidades se definen en dblp.dtd – user61652

+0

¿Pero eso causaría un error de memoria? Tampoco soy un experto en XML, pero creo que las entidades malas como é causarían SAXExceptions en lugar de excepciones de memoria. – Michael

+0

Esa respuesta no tiene ningún beneficio para esta pregunta ... – mark

0

No conozco la terminología correcta para esto, pero ¿cuán "profundo" va tu XML? Por ejemplo, la etiqueta "autor" en su ejemplo tiene 2 elementos de profundidad. Si tiene etiquetas que son realmente muy profundas, ¿quizás es por eso que tiene problemas de memoria?

+0

el nivel más profundo es 2 – user61652

+0

La anidación no debería importar: la cantidad de memoria utilizada por nivel es muy pequeña para SAX y Stax. Quiero decir, no a menos que sean decenas de miles de niveles más o menos. :) – StaxMan

2

Bueno, da:

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

Esto funciona para mí bajo Java 5, pero sí tienen el OOM bajo Java 6.

corro así:

java -DentityExpansLimit=512000 -jar xmltest.jar 

E imprime:

Incollections = 8353 

Que es conveniente:

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

Así, FYI, punto de datos, etc.

+0

Muchas gracias ... Ese era el problema, debería compilar con Java 5 y extender el límite de entidad: Java -DentityExpansionLimit = 512000 Principal – user61652

0

Parece que uno de los segmentos de texto (o CDATA, instrucciones de procesamiento o comentario) en el archivo XML es muy largo y el analizador no lo divide en varios segmentos. O podría ser que el analizador no analice correctamente la declaración DOCTYPE: de ser así, podría intentar leer todo el contenido xml como si fuera parte del subconjunto DTD.

Pero eso es solo especulación. Mencionaste que has probado Stax: ¿qué implementación? JDK 1.6 viene con Sun Sjsxp. Pero también puedes probar Woodstox (http://woodstox.codehaus.org), que a menudo maneja las cosas de una forma un poco más sólida. Entonces, si no está usando Woodstox, podría ver lo que sucede. Sí divide los segmentos de texto en fragmentos más pequeños a menos que fuerce la unión del texto (no por defecto).

Ah, y por si acaso estuvieras probando usando la implementación de referencia de Stax (http://stax.codehaus.org); desafortunadamente se sabe que tiene muchos errores. Entonces eso podría causar problemas. Tanto Sjsxp como Woodstox son opciones mucho mejores con Stax.

Cuestiones relacionadas