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>�</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 �
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 �
en un byte nulo como no válido. :-)
cleaned_s = StringIO(
BeautifulStoneSoup('<test><null>�</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]
.
Hm, sí, la especificación lo deja bastante claro. Gracias por la referencia exacta. – clacke
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. –
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