wake-up-neo.com

Wie schreibt man eine XML-Deklaration mit xml.etree.ElementTree?

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?

41
Roman Alexander

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.

69
wrgrs

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))
20
glormph

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>
11

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

3
alijandro

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>
1
Andriy

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))
0
Alessandro

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)
0
Novak

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="  ")
0
Rebecca Fallon

Einschließlich "Standalone" in der Deklaration

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)
0
G M