Ich generiere ein XML-Dokument in Python mit einer ElementTree
, aber die tostring
-Funktion enthält keine XML-Deklaration , wenn sie in Klartext konvertiert wird.
from xml.etree.ElementTree import Element, tostring
document = Element('outer')
node = SubElement(document, 'inner')
node.NewValue = 1
print tostring(document) # Outputs "<outer><inner /></outer>"
Ich brauche meine Zeichenfolge, um die folgende XML-Deklaration aufzunehmen:
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
Es scheint jedoch keine dokumentierte Methode dafür zu geben.
Gibt es eine geeignete Methode zum Rendern der XML-Deklaration in einer ElementTree
?
Ich bin überrascht zu erfahren, dass es mit ElementTree.tostring()
keinen Weg zu geben scheint. Sie können jedoch ElementTree.ElementTree.write()
verwenden, um Ihr XML-Dokument in eine gefälschte Datei zu schreiben:
from io import BytesIO
from xml.etree import ElementTree as ET
document = ET.Element('outer')
node = ET.SubElement(document, 'inner')
et = ET.ElementTree(document)
f = BytesIO()
et.write(f, encoding='utf-8', xml_declaration=True)
print(f.getvalue()) # your XML file, encoded as UTF-8
Siehe diese Frage . Ich glaube auch nicht, dass Sie Ihr eigenständiges Attribut erhalten können, ohne dass Sie es selbst schreiben.
Ich würde lxml verwenden (siehe http://lxml.de/api.html ).
Dann kannst du:
from lxml import etree
document = etree.Element('outer')
node = etree.SubElement(document, 'inner')
print(etree.tostring(document, xml_declaration=True))
Wenn Sie den encoding='utf8'
angeben, erhalten Sie einen XML-Header :
xml.etree.ElementTree.tostring schreibt eine XML-Codierungsdeklaration mit encoding = 'utf8'
Beispielcode für Python 2:
import xml.etree.ElementTree as ElementTree
tree = ElementTree.ElementTree(
ElementTree.fromstring('<xml><test>123</test></xml>')
)
root = tree.getroot()
print 'without:'
print ElementTree.tostring(root, method='xml')
print
print 'with:'
print ElementTree.tostring(root, encoding='utf8', method='xml')
Ausgabe:
without:
<xml><test>123</test></xml>
with:
<?xml version='1.0' encoding='utf8'?>
<xml><test>123</test></xml>
Dieses Problem ist vor kurzem aufgetreten. Nachdem ich den Code etwas ausgegraben hatte, stellte ich fest, dass der folgende Code-Ausschnitt die Definition der Funktion ElementTree.write
ist.
def write(self, file, encoding="us-ascii"):
assert self._root is not None
if not hasattr(file, "write"):
file = open(file, "wb")
if not encoding:
encoding = "us-ascii"
Elif encoding != "utf-8" and encoding != "us-ascii":
file.write("<?xml version='1.0' encoding='%s'?>\n" %
encoding)
self._write(file, self._root, encoding, {})
Die Antwort lautet also: Wenn Sie den XML-Header in Ihre Datei schreiben müssen, setzen Sie das encoding
-Argument anders als utf-8
oder us-ascii
, z. UTF-8
Das Minimalbeispiel für die Verwendung von ElementTree
:
import xml.etree.ElementTree as ET
document = ET.Element('outer')
node = ET.SubElement(document, 'inner')
node.text = '1'
res = ET.tostring(document, encoding='utf8', method='xml').decode()
print(res)
die Ausgabe ist:
<?xml version='1.0' encoding='utf8'?>
<outer><inner>1</inner></outer>
Ich würde ET verwenden:
try:
from lxml import etree
print("running with lxml.etree")
except ImportError:
try:
# Python 2.5
import xml.etree.cElementTree as etree
print("running with cElementTree on Python 2.5+")
except ImportError:
try:
# Python 2.5
import xml.etree.ElementTree as etree
print("running with ElementTree on Python 2.5+")
except ImportError:
try:
# normal cElementTree install
import cElementTree as etree
print("running with cElementTree")
except ImportError:
try:
# normal ElementTree install
import elementtree.ElementTree as etree
print("running with ElementTree")
except ImportError:
print("Failed to import ElementTree from any known place")
document = etree.Element('outer')
node = etree.SubElement(document, 'inner')
print(etree.tostring(document, encoding='UTF-8', xml_declaration=True))
Eine weitere recht einfache Möglichkeit besteht darin, den gewünschten Header mit der Zeichenfolge von XML wie folgt zu verketten:
xml = (bytes('<?xml version="1.0" encoding="UTF-8"?>\n', encoding='utf-8') + ET.tostring(root))
xml = xml.decode('utf-8')
with open('invoice.xml', 'w+') as f:
f.write(xml)
Dies funktioniert, wenn Sie nur drucken möchten. Beim Versuch, es an eine Datei zu senden, wird eine Fehlermeldung angezeigt ...
import xml.dom.minidom as minidom
import xml.etree.ElementTree as ET
from xml.etree.ElementTree import Element, SubElement, Comment, tostring
def prettify(elem):
rough_string = ET.tostring(elem, 'utf-8')
reparsed = minidom.parseString(rough_string)
return reparsed.toprettyxml(indent=" ")
Ich habe keine Alternative für das Hinzufügen des Arguments standalone
in der Dokumentation gefunden. Daher habe ich die Funktion ET.tosting
angepasst, um sie als Argument zu verwenden.
from xml.etree import ElementTree as ET
# Sample
document = ET.Element('outer')
node = ET.SubElement(document, 'inner')
et = ET.ElementTree(document)
# Function that you need
def tostring(element, declaration, encoding=None, method=None,):
class dummy:
pass
data = []
data.append(declaration+"\n")
file = dummy()
file.write = data.append
ET.ElementTree(element).write(file, encoding, method=method)
return "".join(data)
# Working example
xdec = """<?xml version="1.0" encoding="UTF-8" standalone="no" ?>"""
xml = tostring(document, encoding='utf-8', declaration=xdec)