Konvertieren Sie Python ElementTree in einen String

84

Bei jedem Anruf ElementTree.tostring(e)wird folgende Fehlermeldung angezeigt:

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

Gibt es eine andere Möglichkeit, ein ElementTree-Objekt in eine XML-Zeichenfolge zu konvertieren?

Zurück verfolgen:

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'
Stevoisiak
quelle

Antworten:

106

ElementObjekte haben keine .getroot()Methode. Beenden Sie diesen Anruf, und der .tostring()Anruf funktioniert:

xmlstr = ElementTree.tostring(et, encoding='utf8', method='xml')
Martijn Pieters
quelle
6
Für Spätankömmlinge aus Suchmaschinen: Wenn die Codierung 'utf8' lautet, wird der <?xml version='1.0' encoding='utf8'?>Header vorangestellt . Wenn es utf-8der Header ist, ist er nicht enthalten. Auch wenn etes sich um einen ElementTree handelt, muss man bestehen et.getroot().
Kenji Noguchi
23
encoding='utf8'Gibt in Python 3 einen Bytestring anstelle eines Strings zurück. Ich empfehle tostring(xml, encoding="unicode")stattdessen zu verwenden .
Stevoisiak
1
@StevenVascellaro: XML ist wirklich ein Binärformat , da das Datenformat aus Bytes in einer bestimmten Codierung besteht (angegeben in der XML-Deklaration oben, standardmäßig UTF-8, falls nicht vorhanden). In Python 2 strhandelt es sich um dieselbe Art von Objekt wie in bytesPython 3. Die Ausgabe von Bytes ist völlig korrekt, unicodeda die Ausgabe im Wesentlichen eine Ergänzung ist, mit der Sie vermeiden müssen, dass Sie dekodieren müssen, wenn Sie stattdessen eine Unicode-Zeichenfolge für Ihren speziellen Anwendungsfall benötigen.
Martijn Pieters
Laut helpwird nur encoding="unicode"eine Zeichenfolge zurückgegeben.
cz
45

Wie konvertiere ich ElementTree.Elementin einen String?

Für Python 3:

xml_str = ElementTree.tostring(xml, encoding='unicode')

Für Python 2:

xml_str = ElementTree.tostring(xml, encoding='utf-8')

Zur Kompatibilität mit Python 2 und 3:

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

Anwendungsbeispiel

from xml.etree import ElementTree

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

Ausgabe:

<Person Name="John" />

Erläuterung

Ungeachtet dessen, was der Name andeutet, ElementTree.tostring()wird in Python 2 und 3 standardmäßig ein Bytestring zurückgegeben. Dies ist ein Problem in Python 3, das Unicode für Zeichenfolgen verwendet .

In Python 2 können Sie den strTyp sowohl für Text- als auch für Binärdaten verwenden . Leider könnte dieses Zusammentreffen zweier unterschiedlicher Konzepte zu sprödem Code führen, der manchmal für beide Arten von Daten funktioniert, manchmal nicht. [...]

Um die Unterscheidung zwischen Text und Binärdaten klarer und deutlicher zu machen, hat [Python 3] Text- und Binärdaten zu unterschiedlichen Typen gemacht, die nicht blind miteinander gemischt werden können .

Quelle: Portierung von Python 2-Code nach Python 3

Wenn wir wissen, welche Version von Python verwendet wird, können wir die Codierung als unicodeoder angeben utf-8. Wenn wir andernfalls Kompatibilität mit Python 2 und 3 benötigen, können wir decode()in den richtigen Typ konvertieren.

Als Referenz habe ich einen Vergleich der .tostring()Ergebnisse zwischen Python 2 und Python 3 beigefügt .

ElementTree.tostring(xml)
# Python 3: b'<Person Name="John" />'
# Python 2: <Person Name="John" />

ElementTree.tostring(xml, encoding='unicode')
# Python 3: <Person Name="John" />
# Python 2: LookupError: unknown encoding: unicode

ElementTree.tostring(xml, encoding='utf-8')
# Python 3: b'<Person Name="John" />'
# Python 2: <Person Name="John" />

ElementTree.tostring(xml).decode()
# Python 3: <Person Name="John" />
# Python 2: <Person Name="John" />

Vielen Dank an Martijn Peters für den Hinweis, dass sich der strDatentyp zwischen Python 2 und 3 geändert hat.


Warum nicht str () verwenden?

In den meisten Szenarien ist die Verwendung str()die " kanonische " Methode, um ein Objekt in eine Zeichenfolge zu konvertieren. ElementWenn Sie dies mit verwenden, wird die Position des Objekts im Speicher leider als Hexstring und nicht als String-Darstellung der Objektdaten zurückgegeben.

from xml.etree import ElementTree

xml = ElementTree.Element("Person", Name="John")
print(str(xml))  # <Element 'Person' at 0x00497A80>
Stevoisiak
quelle
1
In Python 2 wird ElementTree.tostring()auch ein Bytestring generiert. Der strTyp ist ein Bytestring in Python 2 (der strTyp von Python 3 wird unicodein Python 2 aufgerufen ).
Martijn Pieters
1
Diese Funktion wurde nur der Python 3-Version hinzugefügt und nicht in Python 2 zurückportiert. Wenn dies der Fall wäre, würden Sie eine unicodeZeichenfolge zurückerhalten.
Martijn Pieters
0

Nicht-lateinische Antworterweiterung

Erweiterung der Antwort von @ Stevoisiak und Umgang mit nicht-lateinischen Zeichen. Nur eine Möglichkeit zeigt Ihnen die nicht-lateinischen Zeichen an. Die eine Methode unterscheidet sich sowohl in Python 3 als auch in Python 2.

Eingang

xml = ElementTree.fromstring('<Person Name="크리스" />')
xml = ElementTree.Element("Person", Name="크리스")  # Read Note about Python 2

HINWEIS: In Python 2 wird beim Aufrufen des toString(...)Codes beim Zuweisen xmlmit ElementTree.Element("Person", Name="크리스")ein Fehler ausgelöst ...

UnicodeDecodeError: 'ascii' codec can't decode byte 0xed in position 0: ordinal not in range(128)

Ausgabe

ElementTree.tostring(xml)
# Python 3 (크리스): b'<Person Name="&#53356;&#47532;&#49828;" />'
# Python 3 (John): b'<Person Name="John" />'

# Python 2 (크리스): <Person Name="&#53356;&#47532;&#49828;" />
# Python 2 (John): <Person Name="John" />


ElementTree.tostring(xml, encoding='unicode')
# Python 3 (크리스): <Person Name="크리스" />             <-------- Python 3
# Python 3 (John): <Person Name="John" />

# Python 2 (크리스): LookupError: unknown encoding: unicode
# Python 2 (John): LookupError: unknown encoding: unicode

ElementTree.tostring(xml, encoding='utf-8')
# Python 3 (크리스): b'<Person Name="\xed\x81\xac\xeb\xa6\xac\xec\x8a\xa4" />'
# Python 3 (John): b'<Person Name="John" />'

# Python 2 (크리스): <Person Name="크리스" />             <-------- Python 2
# Python 2 (John): <Person Name="John" />

ElementTree.tostring(xml).decode()
# Python 3 (크리스): <Person Name="&#53356;&#47532;&#49828;" />
# Python 3 (John): <Person Name="John" />

# Python 2 (크리스): <Person Name="&#53356;&#47532;&#49828;" />
# Python 2 (John): <Person Name="John" />

Christopher Rucinski
quelle