2009-10-02 15 views
5

Sto cercando di analizzare * un file di grandi dimensioni (> 5 GB) di dati di markup strutturati. Il formato dei dati è essenzialmente XML ma non esiste un elemento radice esplicito. Qual è il modo più efficace per farlo?Analisi di file pseudo-xml di grandi dimensioni in python

Il problema con i parser SAX è che richiedono un elemento root, quindi o devo aggiungere uno pseudoelemento al flusso di dati (c'è un equivalente a SequenceInputStream di Java in Python?) O devo passare a un parser basato sugli eventi non SAX conforme (esiste un successore di sgmllib?)

La struttura dei dati è piuttosto semplice. Fondamentalmente un elenco di elementi:

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

* in realtà per iterare

risposta

11

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

Nota, che è possibile passare un oggetto 'flusso' di xml.sax.parse. Questo significa che probabilmente puoi passare qualsiasi oggetto che abbia metodi di tipo file (come read) alla chiamata parse ... Crea il tuo oggetto, che in primo luogo metterà il tag di inizio della root virtuale, quindi il contenuto del file, quindi la radice virtuale fine-tag. Immagino che tu debba solo implementare il metodo read ... ma questo potrebbe dipendere dal parser sax che userai.

Esempio che funziona per me:

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

è 'ritorno ''' davvero la cosa giusta da fare su 'StopIteration'? Come fa un client di quel codice a notare l'EOF se usa solo 'read()' allora? –

+4

Una delle proprietà degli oggetti stream-like in python è che una chiamata read() blocca e restituisce almeno un byte o, in caso di EOF, restituisce una stringa vuota. Ecco come funziona il metodo file.read originale. – liori

+1

Si potrebbe desiderare di utilizzare questo in combinazione con PullDOM - combina la natura di streaming di SAX con la natura gerarchica di DOM. – RichieHindle

1

La risposta rapida e sporca sarebbe l'aggiunta di un elemento radice (come String) quindi sarebbe un XML valido.

Saluti.

1

elemento Add radice e utilizzare SAX, Stax o VTD-XML ..

+0

Signor Zhang - buona risposta. L'ho svalutato. –

+0

Ho collegato il meta account con questo, dove sono i 100 punti che hai promesso? –

0

xml.parsers.expat - Veloce parsing XML utilizzando Expat Il modulo xml.parsers.expat è un'interfaccia Python per la non Expat -validazione del parser XML. Il modulo fornisce un singolo tipo di estensione, xmlparser, che rappresenta lo stato corrente di un parser XML. Dopo che un oggetto xmlparser è stato creato, vari attributi dell'oggetto possono essere impostati sulle funzioni del gestore. Quando un documento XML viene quindi inviato al parser, le funzioni del gestore vengono richiamate per i dati carattere e il markup nel documento XML.

Maggiori informazioni: http://www.python.org/doc/2.5/lib/module-xml.parsers.expat.html

Problemi correlati