2010-06-14 15 views
5

He escrito una pequeña función, que utiliza elementtree y XPath para extraer el contenido de texto de ciertos elementos en un archivo XML:Python + Expat: Error en � entidades

#!/usr/bin/env python2.5 

import doctest 
from xml.etree import ElementTree 
from StringIO import StringIO 

def parse_xml_etree(sin, xpath): 
    """ 
Takes as input a stream containing XML and an XPath expression. 
Applies the XPath expression to the XML and returns a generator 
yielding the text contents of each element returned. 

>>> parse_xml_etree(
... StringIO('<test><elem1>one</elem1><elem2>two</elem2></test>'), 
... '//elem1').next() 
'one' 
>>> parse_xml_etree(
... StringIO('<test><elem1>one</elem1><elem2>two</elem2></test>'), 
... '//elem2').next() 
'two' 
>>> parse_xml_etree(
... StringIO('<test><null>&#0;</null><elem3>three</elem3></test>'), 
... '//elem2').next() 
'three' 
""" 

    tree = ElementTree.parse(sin) 
    for element in tree.findall(xpath): 
    yield element.text 

if __name__ == '__main__': 
    doctest.testmod(verbose=True) 

La tercera prueba se produce el siguiente excepción:

ExpatError: referencia al número de carácter no válido: línea 1, columna 13

¿Es el XML ilegal &#0; entidad? Independientemente de si lo es o no, los archivos que quiero analizar lo contienen y necesito una forma de analizarlos. ¿Alguna sugerencia para otro analizador que Expat, o configuración para Expat, que me permita hacer eso?


Actualización: Me descubrió BeautifulSoup hace un momento, un analizador de sopa de etiqueta como se indica más adelante en el comentario de respuesta, y para la diversión que regresó a este problema y trató de usarlo como un XML-limpiador en frente de elementtree , pero debidamente convirtió el &#0; en un byte nulo como no válido. :-)

cleaned_s = StringIO(
    BeautifulStoneSoup('<test><null>&#0;</null><elem3>three</elem3></test>', 
        convertEntities=BeautifulStoneSoup.XML_ENTITIES 
).renderContents() 
) 
tree = ElementTree.parse(cleaned_s) 

... rendimientos

xml.parsers.expat.ExpatError: not well-formed (invalid token): line 1, column 12 

En mi caso particular, sin embargo, yo no necesitaba realmente el análisis XPath como tal, podría haber ido con ella misma BeautifulSoup y es bastante sencillo estilo de direccionamiento de nodo parsed_tree.test.elem1.contents[0].

Respuesta

6

&#0; no está en el legal character range definido por la especificación XML. Por desgracia, mis habilidades en Python son bastante rudimentarias, así que no soy de mucha ayuda allí.

+0

Hm, sí, la especificación lo deja bastante claro. Gracias por la referencia exacta. – clacke

+0

Me doy cuenta de que este es un hilo antiguo, pero la especificación dice que los caracteres * literales * solo pueden aparecer en XML. La secuencia de bytes � no es * literalmente * un carácter nulo, sino una secuencia de 4 caracteres que * representa * un byte nulo. Teniendo en cuenta esa distinción, ¿es legal �? No puedo encontrar nada en la especificación que diga * que * es ilegal. –

+1

Una pregunta válida. Pero la respuesta está aquí: http://www.w3.org/TR/REC-xml/#sec-references dice "Los caracteres a los que se hace referencia con referencias de personaje DEBEN coincidir con la producción de Char". – clacke

4

&#0; no es un caracter XML válido. Idealmente, podría lograr que el creador del archivo cambiara su proceso para que el archivo no fuera así.

Si debe aceptar estos archivos, puede preprocesarlos para convertir &#0 en otra cosa. Por ejemplo, elija @ como un carácter de escape, gire "@" en "@@" y "&#0;" en "@ 0".

Luego, cuando obtenga los datos de texto del analizador, puede invertir la asignación. Esto es solo un ejemplo, puedes inventar cualquier sintaxis de escape que te guste.

+0

En mi caso particular, podría simplemente eliminarlos. Están en un elemento irrelevante del XML. Se siente inestable al usar el procesamiento de texto para manejar XML, pero como no está bien formado, creo que no tengo otra opción ... Usar algún tipo de analizador de sopa de etiquetas parece excesivo. – clacke

+0

¿Estás seguro de que el algoritmo de escape es robusto? ¿No tiene que considerar la precedencia de las características dentro de la gramática de XML? –

Cuestiones relacionadas