2009-10-02 23 views
5

Próbuję przeanalizować * duży plik (> 5 GB) struktury danych znaczników. Format danych jest w zasadzie XML, ale nie ma wyraźnego elementu root. Jaki jest najskuteczniejszy sposób na zrobienie tego?Parsowanie dużych plików pseudo-xml w pythonie

Problem z parserami SAX polega na tym, że wymagają one elementu głównego, więc albo muszę dodać pseudo element do strumienia danych (czy jest odpowiednik Java SequenceInputStream w Pythonie?) Lub muszę przejść do parser oparty na zdarzeniach zgodnych z SAX (czy istnieje następca sgmllib?)

Struktura danych jest dość prosta. Zasadniczo wykaz elementów:

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

* faktycznie iteracyjne

Odpowiedz

11

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

uwaga, że ​​można przekazać 'strumień' obiekt do xml.sax.parse. Oznacza to, że prawdopodobnie można przekazać dowolny obiekt, który ma metody podobne do plików (np. read) do wywołania parse ... Stwórz własny obiekt, który najpierw umieści wirtualny plik główny start-tag, a następnie zawartość pliku, a następnie wirtualny root koniec tagu. Domyślam się, że musisz zaimplementować tylko metodę read ... ale może to zależeć od używanego parsera sax.

Przykład, który działa dla mnie:

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

jest 'return ''' naprawdę dobrą rzeczą do zrobienia w 'StopIteration'? W jaki sposób klient tego kodu zauważyłby EOF, gdyby używał tylko 'read()'? –

+4

Jedną z właściwości obiektów strumieniowych w pythonie jest to, że wywołanie read() blokuje i zwraca co najmniej jeden bajt, lub w przypadku EOF zwraca pusty łańcuch. Tak działa oryginalna metoda file.read. – liori

+1

Być może zechcesz użyć tego w połączeniu z PullDOM - łączy on charakter streamingowy SAX z hierarchiczną naturą DOM. – RichieHindle

1

Szybki i brudny odpowiedź będzie dodanie elementu głównego (jako ciąg) tak, że będzie to ważny XML.

Pozdrawiam.

1

Element Dodaj korzeń i używać Sax, Stax lub VTD-xml ..

+0

Mr. Zhang - dobra odpowiedź. Przegrałem to. –

+0

Połączyłem konto meta z tym, gdzie jest 100 punktów, które obiecałeś? –

0

xml.parsers.expat - Szybkie analizowania XML za pomocą Expat Moduł xml.parsers.expat to interfejs Pythona do non Expat - poprawianie analizatora składni XML. Moduł udostępnia pojedynczy typ rozszerzenia xmlparser, który reprezentuje bieżący stan analizatora składni XML. Po utworzeniu obiektu xmlparser różne funkcje obiektu można ustawić na funkcje modułu obsługi. Kiedy dokument XML jest następnie przesyłany do analizatora składni, funkcje obsługi są wywoływane dla danych znakowych i znaczników w dokumencie XML.

Więcej informacji: http://www.python.org/doc/2.5/lib/module-xml.parsers.expat.html