2009-02-03 11 views
5

Question de suivi à Big XML File:RE: Big fichier XML

D'abord merci beaucoup pour vos réponses. Après ... ce que je fais mal? C'est ma classe qui utilise 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 { 

    } 
} 

Vous pouvez voir que je ne fais rien avec mon fichier XML, mais il donne cette erreur:

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) 

J'ai essayé aussi Stax ... la même erreur ... ce Est-ce que je peux faire? Aussi j'augmente la taille de tas Java jusqu'à 1260m

java -Xmx1260M SAXParserXML 

le fichier XML a cette forme:

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

Vous pouvez trouver le fichier d'origine: http://dblp.uni-trier.de/xml/

Merci

+0

Il serait utile que vous nous en disiez plus sur le type de XML que vous analysez. –

Répondre

6

Il y a un bug pour Java 1.6 qui montre exactement la même trace de pile, et il est non fixé à ce jour. Les versions plus récentes de Xerces semblent aller bien.

Pour les documents de cette taille, qui contiennent encore une bonne quantité de structure, vous pouvez envisager d'utiliser l'analyse par extraction, c'est-à-dire l'analyse de structures partielles, par exemple avec StAX.

+0

J'ai déjà essayé Stax ... il donne la même erreur – user61652

+0

S'il donne la même trace de pile, vous n'utilisez pas StAX. Quelle est la trace de pile pour StAX? – lavinio

+0

Je pense que j'ai le même problème que le sujet de départ. La page de bug indique que le bug est fermé ... Mais est-ce vraiment corrigé? J'utilise JDK 6 Update 23 sur Windows XP. –

0

Il semble y avoir un problème avec les entites HTML dans votre code, à savoir "Jos &eacute;" dans le premier bloc. Au moins, mon navigateur me dit qu'il y a un problème avec ce fichier lorsque j'ouvre le fichier, et XMLEntityScanner apparaît dans la trace de la pile. Je ne suis pas un expert XML, mais est-ce que les entités HTML ne sont pas définies pour XML en général?

Modifier Oui, c'est ça. Selon Wikipedia, des entités telles que &eacute; sont définies dans la DTD HTML; XML n'a qu'un très petit nombre d'entités prédéfinies.

+0

Toutes les entités sont définies dans dblp.dtd – user61652

+0

Mais cela provoquerait-il une erreur de mémoire? Je ne suis pas non plus un expert XML, mais je pense que les mauvaises entités comme é provoqueraient des exceptions SAX par opposition aux exceptions de mémoire. – Michael

+0

Cette réponse n'est d'aucun avantage que ce soit à cette question ... – mark

0

Je ne connais pas la bonne terminologie pour cela, mais à quel point votre code XML est-il «profond»? Par exemple, la balise "author" dans votre exemple a 2 éléments de profondeur. Si vous avez des tags qui sont vraiment très profonds, c'est peut-être pourquoi vous avez des problèmes de mémoire?

+0

le niveau le plus profond est 2 – user61652

+0

L'imbrication ne devrait vraiment pas avoir d'importance: la quantité de mémoire utilisée par niveau est très faible pour SAX et Stax. Je veux dire, pas à moins qu'il ne s'agisse de dizaines de milliers de niveaux. :) – StaxMan

2

Eh bien, étant donné:

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

Cela fonctionne pour moi sous Java 5, mais je reçois le OOM sous Java 6.

Je cours comme ceci:

java -DentityExpansLimit=512000 -jar xmltest.jar 

Et il imprime:

Incollections = 8353 

Ce qui est pratique:

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

Ainsi, FYI, point de données, etc.

+0

Merci beaucoup ... C'était le problème, je devrais compiler avec Java 5 et étendre la limite d'entité: Java -DentityExpansionLimit = 512000 Main – user61652

0

Il semble que l'un des segments de texte (ou CDATA, instruction de traitement ou commentaire) dans un fichier XML soit très long et que l'analyseur ne le divise pas en plusieurs segments. Ou il se peut que l'analyseur n'analyse pas correctement la déclaration DOCTYPE: si c'est le cas, il peut essayer de lire tout le contenu xml comme s'il faisait partie du sous-ensemble DTD.

Mais c'est juste de la spéculation. Vous avez mentionné que vous avez essayé Stax: quelle implémentation? JDK 1.6 est livré avec Sun Sjsxp. Mais vous pouvez également essayer Woodstox (http://woodstox.codehaus.org), qui gère souvent les choses de manière un peu plus robuste. Donc, si vous n'utilisez pas Woodstox, vous pouvez voir ce qui se passe. Il divise les segments de texte en morceaux plus petits, sauf si vous forcez la fusion de texte (pas par défaut).

Oh et juste au cas où vous étiez en train de tester en utilisant l'implémentation de référence Stax (http://stax.codehaus.org); il est malheureusement connu pour être très buggé. Cela pourrait donc causer des problèmes. Sjsxp et Woodstox sont des choix bien meilleurs avec Stax.