Antworten:
Heutzutage ist die beliebteste (und sehr einfache) Option die ElementTree-API , die seit Python 2.5 in der Standardbibliothek enthalten ist.
Die verfügbaren Optionen dafür sind:
Hier ist ein Beispiel, wie Sie Ihr Beispieldokument mit dem in-stdlib cElementTree generieren:
import xml.etree.cElementTree as ET
root = ET.Element("root")
doc = ET.SubElement(root, "doc")
ET.SubElement(doc, "field1", name="blah").text = "some value1"
ET.SubElement(doc, "field2", name="asdfasd").text = "some vlaue2"
tree = ET.ElementTree(root)
tree.write("filename.xml")
Ich habe es getestet und es funktioniert, aber ich gehe davon aus, dass Leerzeichen nicht signifikant sind. Wenn Sie einen "Prettyprint" -Einzug benötigen, lassen Sie es mich wissen und ich werde nachschlagen, wie das geht. (Möglicherweise handelt es sich um eine LXML-spezifische Option. Ich verwende die stdlib-Implementierung nicht häufig.)
Zur weiteren Lektüre hier einige nützliche Links:
Abschließend sei angemerkt, dass entweder cElementTree oder LXML für alle Ihre Anforderungen schnell genug sein sollten (beide sind optimierter C-Code) Die LXML-Site gibt Folgendes an:
xml_declaration=True
wenn Sie eine Codierung angeben. Um ein gleichwertiges Verhalten zu erzielen , rufen Sie Folgendes auf tree.write()
: tree.write("filename.xml", xml_declaration=True, encoding='utf-8')
Sie können jede Codierung verwenden, solange Sie dies explizit angeben einer. ( ascii
Erzwingt, dass alle Unicode-Zeichen außerhalb des 7-Bit-ASCII-Satzes
vlaue2
zu value2
: Der Tippfehler in der gewünschten XML - Ausgabe in der ursprünglichen Frage. Bis sich das ändert, die Tippfehler hier tatsächlich ist richtig.
cElementTree
wurde in Python 3.3 abgeschrieben
Die lxml-Bibliothek enthält eine sehr praktische Syntax für die XML-Generierung, die E-Factory . So würde ich das Beispiel machen, das Sie geben:
#!/usr/bin/python
import lxml.etree
import lxml.builder
E = lxml.builder.ElementMaker()
ROOT = E.root
DOC = E.doc
FIELD1 = E.field1
FIELD2 = E.field2
the_doc = ROOT(
DOC(
FIELD1('some value1', name='blah'),
FIELD2('some value2', name='asdfasd'),
)
)
print lxml.etree.tostring(the_doc, pretty_print=True)
Ausgabe:
<root>
<doc>
<field1 name="blah">some value1</field1>
<field2 name="asdfasd">some value2</field2>
</doc>
</root>
Es unterstützt auch das Hinzufügen zu einem bereits erstellten Knoten, z. B. nach dem oben Gesagten
the_doc.append(FIELD2('another value again', name='hithere'))
getattr
z getattr(E, "some-tag")
.
Yattag http://www.yattag.org/ oder https://github.com/leforestier/yattag bietet eine interessante API zum Erstellen eines solchen XML-Dokuments (und auch von HTML-Dokumenten).
Es verwendet Kontextmanager und with
Schlüsselwort.
from yattag import Doc, indent
doc, tag, text = Doc().tagtext()
with tag('root'):
with tag('doc'):
with tag('field1', name='blah'):
text('some value1')
with tag('field2', name='asdfasd'):
text('some value2')
result = indent(
doc.getvalue(),
indentation = ' '*4,
newline = '\r\n'
)
print(result)
So erhalten Sie:
<root>
<doc>
<field1 name="blah">some value1</field1>
<field2 name="asdfasd">some value2</field2>
</doc>
</root>
Für die einfachste Wahl würde ich mich für minidom entscheiden: http://docs.python.org/library/xml.dom.minidom.html . Es ist in die Python-Standardbibliothek integriert und in einfachen Fällen unkompliziert zu verwenden.
Hier ist ein ziemlich einfach zu befolgendes Tutorial: http://www.boddie.org.uk/python/XML_intro.html
Für eine so einfache XML-Struktur möchten Sie möglicherweise kein vollständiges XML-Modul einbeziehen. Betrachten Sie eine Zeichenfolgenvorlage für die einfachsten Strukturen oder Jinja für etwas Komplexeres. Jinja kann eine Liste von Daten durchlaufen, um die innere XML Ihrer Dokumentliste zu erstellen. Bei rohen Python-String-Vorlagen ist das etwas schwieriger
Ein Jinja-Beispiel finden Sie in meiner Antwort auf eine ähnliche Frage .
Hier ist ein Beispiel für das Generieren Ihrer XML mit Zeichenfolgenvorlagen.
import string
from xml.sax.saxutils import escape
inner_template = string.Template(' <field${id} name="${name}">${value}</field${id}>')
outer_template = string.Template("""<root>
<doc>
${document_list}
</doc>
</root>
""")
data = [
(1, 'foo', 'The value for the foo document'),
(2, 'bar', 'The <value> for the <bar> document'),
]
inner_contents = [inner_template.substitute(id=id, name=name, value=escape(value)) for (id, name, value) in data]
result = outer_template.substitute(document_list='\n'.join(inner_contents))
print result
Ausgabe:
<root>
<doc>
<field1 name="foo">The value for the foo document</field1>
<field2 name="bar">The <value> for the <bar> document</field2>
</doc>
</root>
Der Wehrmutstropfen der Vorlage Ansatz ist , dass Sie nicht entkommen erhalten von <
und >
kostenlos. Ich habe um dieses Problem herum getanzt, indem ich einen Util aus gezogen habexml.sax
Ich habe gerade einen XML-Generator mit der Template-Methode von bigh_29 fertig geschrieben. Dies ist eine gute Möglichkeit, die Ausgabe zu steuern, ohne dass zu viele Objekte im Weg stehen.
Für das Tag und den Wert habe ich zwei Arrays verwendet, eines, das den Tag-Namen und die Position in der Ausgabe-XML angibt, und eines, das auf eine Parameterdatei mit derselben Liste von Tags verweist. Die Parameterdatei hat jedoch auch die Positionsnummer in der entsprechenden Eingabedatei (CSV), aus der die Daten entnommen werden. Auf diese Weise ändert sich das Programm nicht, wenn sich die Position der aus der Eingabedatei eingehenden Daten ändert. Es berechnet dynamisch die Datenfeldposition aus dem entsprechenden Tag in der Parameterdatei.