Ich generiere ein XML-Dokument in Python mit einem ElementTree
, aber die tostring
Funktion enthält keine XML-Deklaration bei der Konvertierung in Klartext.
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 benötige meine Zeichenfolge, um die folgende XML-Deklaration einzuschließen:
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
Es scheint jedoch keinen dokumentierten Weg zu geben, dies zu tun.
Gibt es eine geeignete Methode zum Rendern der XML-Deklaration in einem ElementTree
?
python
xml
elementtree
Roman Alexander
quelle
quelle
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))
quelle
Wenn Sie das einschließen
encoding='utf8'
, erhalten Sie einen XML-Header :Beispiel für Python-Code (funktioniert mit Python 2 und 3):
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'))
Python 2-Ausgabe:
$ python2 example.py without: <xml><test>123</test></xml> with: <?xml version='1.0' encoding='utf8'?> <xml><test>123</test></xml>
Bei Python 3 werden Sie das
b
Präfix beachten, das angibt, dass Byte-Literale zurückgegeben werden (genau wie bei Python 2):$ python3 example.py without: b'<xml><test>123</test></xml>' with: b"<?xml version='1.0' encoding='utf8'?>\n<xml><test>123</test></xml>"
quelle
<?xml version=\'1.0\' encoding=\'utf8\'?>
Elementree.Elementree(Elementree.fromstring(...
und ich erkenne jetzt, dassfromstring
einelement
nicht ein zurückgegeben wirdElementTree
, während dieparse
Methode ein zurückgibtElementTree
. Dies macht den Versuch, eine XML-Datei in einer Testsuite mithilfe einer Zeichenfolge zu verspotten, sehr verwirrend! Wenn Sie dieses Element nehmen und ausführentostring
, werden diese Codierungs- und Methodenparameter zugelassen, aber in der Ausgabe fehlt die<?xml
Deklarationszeile, und jetzt sehe ich, dass dies nicht das vollständige Dokument ist.utf8
KEINE gültige Zeichencodierungszeichenfolge ist. Aus diesem Grund fügt Python3 die Deklaration hinzu und gibt das Ganze als Bytes anstelle von Zeichenfolgen zurück.encoding='utf-8'
, um gültig zu sein.Ich bin kürzlich auf dieses Problem gestoßen, nachdem ich den Code ein wenig ausgegraben habe. Ich habe festgestellt, dass das folgende Codeausschnitt eine Definition der Funktion ist
ElementTree.write
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 ein
encoding
anderes Argument alsutf-8
oderus-ascii
, zUTF-8
quelle
ElementTree.ElementTree.write()
ist auch dokumentiert, dass es einenxml_declaration
Parameter gibt (siehe die akzeptierte Antwort). HatElementTree.tostring()
aber nicht diesen Parameter, der die Methode war, die in der ursprünglichen Frage gestellt wurde.Das minimale Arbeitsbeispiel mit
ElementTree
Paketnutzung: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>
quelle
Eine andere ziemlich einfache Option besteht darin, den gewünschten Header wie folgt mit der XML-Zeichenfolge 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)
quelle
Einfach
Beispiel für Python 2 und 3 ( Codierungsparameter muss utf8 sein ):
import xml.etree.ElementTree as ElementTree tree = ElementTree.ElementTree(ElementTree.fromstring('<xml><test>123</test></xml>')) root = tree.getroot() print(ElementTree.tostring(root, encoding='utf8', method='xml'))
Ab Python 3.8 gibt es den Parameter xml_declaration für dieses Zeug:
Beispiel für Python 3.8 und höher:
import xml.etree.ElementTree as ElementTree tree = ElementTree.ElementTree(ElementTree.fromstring('<xml><test>123</test></xml>')) root = tree.getroot() print(ElementTree.tostring(root, encoding='unicode', method='xml', xml_declaration=True))
quelle
xml_declaration Argument
JA, und es besteht keine Notwendigkeit, die
.tostring
Funktion zu verwenden. Gemäß der ElementTree-Dokumentation sollten Sie ein ElementTree-Objekt erstellen, Element und Unterelemente erstellen, die Wurzel des Baums festlegen und schließlich dasxml_declaration
Argument in verwenden.write
function verwenden, damit die Deklarationszeile in der Ausgabedatei enthalten ist.Sie können es so machen:
import xml.etree.ElementTree as ET tree = ET.ElementTree("tree") document = ET.Element("outer") node1 = ET.SubElement(document, "inner") node1.text = "text" tree._setroot(document) tree.write("./output.xml", encoding = "UTF-8", xml_declaration = True)
Und die Ausgabedatei lautet:
<?xml version='1.0' encoding='UTF-8'?> <outer><inner>text</inner></outer>
quelle
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))
quelle
Dies funktioniert, wenn Sie nur drucken möchten. Beim Versuch, es an eine Datei zu senden, wird ein Fehler 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=" ")
quelle
Aufnahme von "Standalone" in die Erklärung
Ich habe keine Alternative zum Hinzufügen des
standalone
Arguments in der Dokumentation gefunden und dieET.tosting
Funktion so angepasst , dass sie als Argument verwendet wird.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)
quelle