library example etree dict create python xml marshalling elementtree

example - Convierta Python ElementTree en una cadena



xml python 3 (2)

Cada vez que llamo a ElementTree.tostring(e) , aparece el siguiente mensaje de error:

AttributeError: ''Element'' object has no attribute ''getroot''

¿Hay alguna otra forma de convertir un objeto ElementTree en una cadena XML?

Rastrear:

Traceback (most recent call last): File "Development/Python/REObjectSort/REObjectResolver.py", line 145, in <module> cm = integrateDataWithCsv(cm, csvm) File "Development/Python/REObjectSort/REObjectResolver.py", line 137, in integrateDataWithCsv xmlstr = ElementTree.tostring(et.getroot(),encoding=''utf8'',method=''xml'') AttributeError: ''Element'' object has no attribute ''getroot''


¿Cómo convierto ElementTree.Element a una cadena?

Para una solución que funcione en Python 2 y 3, use .tostring() y .decode() .

xml_str = ElementTree.tostring(xml).decode()

Ejemplo de uso

from xml.etree import ElementTree xml = ElementTree.Element("Person", Name="John") xml_str = ElementTree.tostring(xml).decode() print(xml_str)

Salida:

<Person Name="John" />

Explicación

A pesar de lo que su nombre implica, .tostring() no devuelve una cadena por defecto . El comportamiento predeterminado es generar una cadena de bytes . Si bien esto no era un problema en Python 2, los dos tipos se hicieron más distintos en Python 3.

En Python 2 puede usar el tipo str para texto y datos binarios . Desafortunadamente, esta confluencia de dos conceptos diferentes podría llevar a un código frágil que a veces funcionaba para cualquier clase de datos, a veces no. [...]

Para hacer que la distinción entre el texto y los datos binarios sea más clara y pronunciada, Python 3 [...] creó tipos de texto y datos binarios distintos que no se pueden combinar a ciegas .

Fuente: Porting Python 2 Code to Python 3

Podemos resolver esta ambigüedad utilizando .decode() para convertir explícitamente nuestra cadena de bytes en texto normal. Esto garantiza la compatibilidad con Python 2 y Python 3.

  • Para la compatibilidad con Python 2 y 3: ElementTree.tostring(xml).decode()
  • Para compatibilidad con Python 3: ElementTree.tostring(xml, encoding=''unicode'', method=''xml'')

Como referencia, he incluido una comparación de los .tostring() de .tostring() entre Python 2 y Python 3.

ElementTree.tostring(xml).decode() # Python 3: <Person Name="John" /> # Python 2: <Person Name="John" /> ElementTree.tostring(xml, encoding=''unicode'', method=''xml'') # Python 3: <Person Name="John" /> # Python 2: LookupError: unknown encoding: unicode ElementTree.tostring(xml, encoding=''utf-8'', method=''xml'') # Python 3: b''<Person Name="John" />'' # Python 2: <Person Name="John" /> ElementTree.tostring(xml, encoding=''utf8'', method=''xml'') # Python 3: b''<?xml version=/'1.0/' encoding=/'utf8/'?>/n<Person Name="John" />'' # Python 2: <?xml version=''1.0'' encoding=''utf8''?> # <Person Name="John" />

Gracias a Martijn Peters por señalar que el tipo de datos str cambió entre Python 2 y 3.

¿Por qué no usar str ()?

En la mayoría de los escenarios, usar str() sería la forma " cannonical " de convertir un objeto en una cadena. Desafortunadamente, el uso de esto con Element devuelve la ubicación del objeto en la memoria como una cadena de hex, en lugar de una representación de cadena de los datos del objeto.

from xml.etree import ElementTree xml = ElementTree.Element("Person", Name="John") print(str(xml)) # <Element ''Person'' at 0x00497A80>


Element objetos del Element no tienen el método .getroot() . .tostring() esa llamada y la llamada .tostring() funciona:

xmlstr = ElementTree.tostring(et, encoding=''utf8'', method=''xml'')