2009-10-02 1933 views
5

Estoy tratando de analizar * un archivo grande (> 5GB) de datos estructurados de marcado. El formato de datos es esencialmente XML, pero no hay un elemento raíz explícito. ¿Cuál es la forma más eficiente de hacer eso?Analizando archivos pseudo-xml grandes en python

El problema con los analizadores SAX es que requieren un elemento raíz, por lo que debo agregar un pseudo elemento a la secuencia de datos (¿existe un equivalente a SequenceInputStream de Java en Python?) O tengo que cambiar a un analizador basado en eventos no conformado por SAX (¿hay un sucesor de sgmllib?)

La estructura de los datos es bastante simple. Básicamente una lista de elementos:

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

* realidad para iterar

Respuesta

11

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

Nota, que se puede pasar un objeto 'arroyo' a xml.sax.parse. Esto significa que probablemente pueda pasar cualquier objeto que tenga métodos similares a archivos (como read) a la llamada parse ... Cree su propio objeto, que primero colocará su etiqueta raíz de inicio virtual, luego el contenido del archivo y luego la raíz virtual etiqueta final Supongo que solo necesita implementar el método read ... pero esto podría depender del analizador de saxofón que usará.

ejemplo que funciona para mí:

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

es 'retorno ''' realmente lo que hay que hacer en 'StopIteration'? ¿Cómo notará un cliente de ese código el EOF si solo usara 'leer()' entonces? –

+4

Una de las propiedades de los objetos similares a secuencias en python es que una llamada de lectura() bloquea o devuelve al menos un byte, o en el caso de EOF, devuelve cadena vacía. Así es como funciona el método file.read original. – liori

+1

Es posible que desee utilizar esto junto con PullDOM: combina la naturaleza de transmisión de SAX con la naturaleza jerárquica de DOM. – RichieHindle

1

La respuesta rápida y sucia sería añadir un elemento raíz (Cadena) por lo que habría un XML válido.

Atentamente.

1

elemento Agregar raíz y utilizar SAX, Stax o ETV-XML ..

+0

Sr. Zhang - buena respuesta. Lo he votado arriba. –

+0

He vinculado la meta cuenta con esta, ¿dónde están los 100 puntos que prometiste? –

0

xml.parsers.expat - análisis de XML rápido usando expatriado El módulo xml.parsers.expat es una interfaz de Python para la no expatriados -validando el analizador XML. El módulo proporciona un único tipo de extensión, xmlparser, que representa el estado actual de un analizador XML. Después de que se ha creado un objeto xmlparser, varios atributos del objeto se pueden configurar para las funciones del manejador. Cuando un documento XML se alimenta al analizador, las funciones del manejador se llaman para los datos del carácter y el marcado en el documento XML.

Más información: http://www.python.org/doc/2.5/lib/module-xml.parsers.expat.html