2010-08-04 12 views
11

Tengo un archivo XML que especifica una codificación, y uso UnicodeDammit para convertirlo a Unicode (por razones de almacenamiento, no puedo almacenarlo como una cadena). Luego lo paso a lxml pero se niega a ignorar la codificación especificada en el archivo y analizarlo como Unicode, y se genera una excepción.¿Hay alguna manera de obligar a lxml a analizar las cadenas Unicode que especifican una codificación en una etiqueta?

¿Cómo puedo forzar a lxml a analizar el documento? Este comportamiento parece demasiado restrictivo.

Respuesta

3

Básicamente, la solución es hacer:

if isinstance(mystring, unicode): 
    mystring = mystring.encode("utf-8") 

serio. Buen trabajo, lxml.

EDITAR: Resulta que, en este caso, lxml autodetecta la codificación incorrectamente. Parece que tendré que buscar manualmente y eliminar "juego de caracteres" y "codificación" de la página.

15

No puede analizar cadenas unicode Y tiene una declaración de codificación en la cadena. Entonces, o la convierte en una cadena codificada (ya que al parecer no puede almacenarla como una cadena, deberá volver a codificarla antes de analizarla) o serializar el árbol como unicode con lxml usted mismo: etree.tostring(tree, encoding=unicode), SIN declaración xml . se puede analizar fácilmente el resultado de nuevo con etree.fromunicode

ver http://lxml.de/parsing.html#python-unicode-strings

Editar:. Si, al parecer, ya tiene la cadena unicode, y no se puede controlar la forma en que se hizo que tendrá que codificarlo de nuevo y proporcionarle al analizador la codificación que utilizó:

utf8_parser = etree.XMLParser(encoding='utf-8') 

def parse_from_unicode(unicode_str): 
    s = unicode_str.encode('utf-8') 
    return etree.fromstring(s, parser=utf8_parser) 

Esto asegurará que se ignore lo que haya dentro de la declaración xml, ya que el analizador siempre usará utf-8.

+0

Todo el problema es que no puedo conseguir un árbol en primer lugar, si pudiera me wouldn' t tiene algún problema ... –

+0

@Stavros Korokithakis, etree es un módulo, no el árbol analizado. –

+0

@Daniel Kluev: Sí, pero "árbol" es un árbol. –

0

La solución NO es volver a codificar la cadena. La declaración de codificación dentro de la cadena puede decir algo que no sea UTF8. No vuelva a codificar ciegamente a utf8 y espere que funcione todo el tiempo.

La solución es simplemente quitar la declaración de codificación. ¡Ya tiene a mano una cadena Unicode, ya no es necesaria!

# this is from lxml/apihelpers.pxi 
RE_XML_ENCODING = re.compile(
    ur'^(<\?xml[^>]+)\s+encoding\s*=\s*["\'][^"\']*["\'](\s*\?>|)', re.U) 

RE_XML_ENCODING.sub("", broken_xml_string, count=1) 

El peor de los casos (donde ninguna declaración XML codificación se encontró) Tiempo de complejidad aquí es O (n), que es bastante malo (pero aún mejor que ciegamente a la codificación binaria), así que estoy abierto a sugerencias aquí .

PS: Algunos análisis interesantes del problema xml codificación:

default encoding for XML is UTF-8 or UTF-16?

How default is the default encoding (UTF-8) in the XML Declaration?

Cuestiones relacionadas