2009-10-02 9 views
5

J'essaye d'analyser * un gros fichier (> 5 Go) de données de balisage structurées. Le format de données est essentiellement XML mais il n'y a pas d'élément racine explicite. Quel est le moyen le plus efficace de le faire? Le problème avec les parseurs SAX est qu'ils nécessitent un élément racine, donc soit je dois ajouter un pseudo-élément au flux de données (y a-t-il un équivalent à SequenceInputStream de Java en Python?), Soit je dois passer à un analyseur basé sur les événements non conforme à SAX (existe-t-il un successeur de sgmllib?)Analyse de gros fichiers pseudo-xml en python

La structure des données est assez simple. Fondamentalement, une liste des éléments:

<Document> 
    <docid>1</docid> 
    <text>foo</text> 
</Document> 
<Document> 
    <docid>2</docid> 
    <text>bar</text> 
</Document> 

* en fait itérer

Répondre

11

http://docs.python.org/library/xml.sax.html

Notez que vous pouvez passer un objet 'stream' à xml.sax.parse. Cela signifie que vous pouvez probablement passer n'importe quel objet ayant des méthodes semblables à des fichiers (comme read) à l'appel parse ... Créez votre propre objet, qui mettra d'abord votre racine de démarrage racine virtuelle, puis le contenu du fichier, puis la racine virtuelle étiquette de fin. Je suppose que vous avez seulement besoin de mettre en œuvre la méthode read ... mais cela peut dépendre de l'analyseur de sax que vous utiliserez.

Exemple qui fonctionne pour moi:

import xml.sax 
import xml.sax.handler 

class PseudoStream(object): 
    def read_iterator(self): 
     yield '<foo>' 
     yield '<bar>' 
     for line in open('test.xml'): 
      yield line 
     yield '</bar>' 
     yield '</foo>' 

    def __init__(self): 
     self.ri = self.read_iterator() 

    def read(self, *foo): 
     try: 
      return self.ri.next() 
     except StopIteration: 
      return '' 

class SAXHandler(xml.sax.handler.ContentHandler): 
    def startElement(self, name, attrs): 
     print name, attrs 

d = xml.sax.parse(PseudoStream(), SAXHandler()) 
+0

est 'retour ''' vraiment la bonne chose à faire sur 'StopIteration'? Comment un client de ce code pourrait-il remarquer l'EOF s'il utilisait seulement 'read()' alors? –

+4

L'une des propriétés des objets de type flux dans python est qu'un appel read() bloque et retourne au moins un octet, ou dans le cas d'EOF, renvoie une chaîne vide. C'est ainsi que fonctionne la méthode originale file.read. – liori

+1

Vous pouvez utiliser ceci en conjonction avec PullDOM - il combine la nature de streaming de SAX avec la nature hiérarchique de DOM. – RichieHindle

1

La réponse rapide et sale serait ajouter un élément racine (comme String) de sorte qu'il serait un XML valide.

Cordialement.

1

élément Ajouter racine et utiliser SAX, Stax ou VTD-XML ..

+0

M. Zhang - bonne réponse. Je l'ai upvoted. –

+0

J'ai lié le compte méta avec celui-ci, où sont les 100 points que vous avez promis? –

0

xml.parsers.expat - analyse XML rapide à l'aide d'expatriés Le module xml.parsers.expat est une interface Python à la non Expat validateur XML validant Le module fournit un type d'extension unique, xmlparser, qui représente l'état actuel d'un analyseur XML. Après la création d'un objet xmlparser, divers attributs de l'objet peuvent être définis sur des fonctions de gestionnaire. Lorsqu'un document XML est ensuite transmis à l'analyseur, les fonctions du gestionnaire sont appelées pour les données de caractères et le balisage dans le document XML.

Plus d'info: http://www.python.org/doc/2.5/lib/module-xml.parsers.expat.html

Questions connexes