Convertir Python ElementTree en chaîne

chaque fois que j'appelle ElementTree.tostring(e) , je reçois le message d'erreur suivant:

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

y a-t-il une autre façon de convertir un objet ElementTree en chaîne XML?

TraceBack:

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'
42
demandé sur Steven Vascellaro 2013-03-09 02:13:28

2 réponses

Element les objets n'ont pas de méthode .getroot() . Lâchez cet appel, et le .tostring() l'appel fonctionne:

xmlstr = ElementTree.tostring(et, encoding='utf8', method='xml')
64
répondu Martijn Pieters 2018-01-31 14:59:41

comment convertir ElementTree.Element en chaîne de caractères?

pour une solution qui fonctionne à la fois en Python 2 et 3, Utilisez .tostring() et .decode() .

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

exemple d'usage

from xml.etree import ElementTree

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

sortie:

<Person Name="John" />

explication

malgré ce que la nom implique, ElementTree.tostring() ne renvoie pas une chaîne de caractères par défaut . Le comportement par défaut est de générer un bytestring . Bien que ce n'était pas un problème en Python 2, Les deux types ont été rendus plus distincts en Python 3.

en Python 2, Vous pouvez utiliser le type str pour le texte et les données binaires . Malheureusement, cette confluence de deux concepts pourrait conduire à code fragile qui a parfois fonctionné pour l'un ou l'autre type de données, parfois pas. [...]

pour rendre la distinction entre texte et données binaires plus claire et plus prononcée, Python 3 [...] fait de types de texte et de données binaires distincts qui ne peuvent pas être mélangés aveuglément ensemble .

Source: porter le Code Python 2 en Python 3

nous pouvons résoudre cette ambiguïté en utilisant decode() pour convertir explicitement notre bytestring en texte régulier. Cela garantit la compatibilité avec Python 2 et Python 3.

  • pour compatibilité Python 2 & 3: ElementTree.tostring(xml).decode()
  • pour compatibilité Python 3: ElementTree.tostring(xml, encoding='unicode', method='xml')

pour référence, j'ai inclus un comparaison des résultats .tostring() entre Python 2 et 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" />

merci à Martijn Peters pour avoir souligné que le type de données str a changé entre Python 2 et 3.


pourquoi ne pas utiliser str()?

dans la plupart des scénarios, en utilisant str() serait le " cannonique " façon de convertir un objet pour une chaîne de caractères. Malheureusement, en utilisant ceci avec Element renvoie l'emplacement de l'objet dans la mémoire comme un hexstring, plutôt qu'une représentation de chaîne de caractères des données de l'objet.

from xml.etree import ElementTree

xml = ElementTree.Element("Person", Name="John")
print(str(xml))  # <Element 'Person' at 0x00497A80>
7
répondu Steven Vascellaro 2018-07-24 19:03:07