Odpowiedzi:
Obecnie najbardziej popularną (i bardzo prostą) opcją jest API ElementTree , które jest dołączone do standardowej biblioteki od czasu Pythona 2.5.
Dostępne opcje to:
Oto przykład tego, jak wygenerować przykładowy dokument przy użyciu cElementTree w standardowej bibliotece:
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")
Przetestowałem to i działa, ale zakładam, że białe spacje nie mają znaczenia. Jeśli potrzebujesz wcięcia „prettyprint”, daj mi znać, a sprawdzę, jak to zrobić. (Może to być opcja specyficzna dla LXML. Nie używam zbyt często implementacji standardowej biblioteki)
Aby uzyskać więcej informacji, oto kilka przydatnych linków:
Na koniec, albo cElementTree, albo LXML powinny być wystarczająco szybkie dla wszystkich twoich potrzeb (oba są zoptymalizowanym kodem C), ale jeśli jesteś w sytuacji, w której musisz wycisnąć każdy ostatni kawałek wydajności, testy porównawcze witryna LXML wskazuje, że:
xml_declaration=True
wtedy, gdy określisz kodowanie ... ale aby uzyskać równoważne zachowanie, wywołaj w tree.write()
ten sposób: tree.write("filename.xml", xml_declaration=True, encoding='utf-8')
Możesz użyć dowolnego kodowania, o ile wyraźnie określisz jeden. ( ascii
wymusi na wszystkich znakach Unicode spoza 7-bitowego zestawu ASCII kodowanie encji, jeśli nie ufasz prawidłowej konfiguracji serwera WWW).
vlaue2
na value2
: the typo jest w wymaganym wyjściu XML w oryginalnym pytanie. Dopóki to się nie zmieni, literówka tutaj jest poprawna.
cElementTree
został zdeprecjonowany w Pythonie 3.3
Biblioteka lxml zawiera bardzo wygodny składni XML generacji, zwany e-fabryka . Oto jak zrobiłbym przykład, który podasz:
#!/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)
Wynik:
<root>
<doc>
<field1 name="blah">some value1</field1>
<field2 name="asdfasd">some value2</field2>
</doc>
</root>
Obsługuje również dodawanie do już utworzonego węzła, np. Po powyższym można by powiedzieć
the_doc.append(FIELD2('another value again', name='hithere'))
getattr
np getattr(E, "some-tag")
.
Yattag http://www.yattag.org/ lub https://github.com/leforestier/yattag udostępnia interesujące API do tworzenia takich dokumentów XML (a także dokumentów HTML).
Używa menedżera kontekstu i with
słowa kluczowego.
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)
więc otrzymasz:
<root>
<doc>
<field1 name="blah">some value1</field1>
<field2 name="asdfasd">some value2</field2>
</doc>
</root>
Najprostszy wybór to minidom: http://docs.python.org/library/xml.dom.minidom.html . Jest wbudowany w standardową bibliotekę Pythona i jest łatwy w użyciu w prostych przypadkach.
Oto całkiem prosty samouczek: http://www.boddie.org.uk/python/XML_intro.html
W przypadku tak prostej struktury XML możesz nie chcieć angażować pełnego modułu XML. Rozważ szablon łańcucha dla najprostszych struktur lub Jinja dla czegoś nieco bardziej złożonego. Jinja może obsłużyć zapętlenie listy danych w celu utworzenia wewnętrznego XML listy dokumentów. Jest to nieco trudniejsze w przypadku szablonów surowych ciągów znaków Pythona
Aby zapoznać się z przykładem Jinja, zobacz moją odpowiedź na podobne pytanie .
Oto przykład generowania pliku XML za pomocą szablonów ciągów.
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
Wynik:
<root>
<doc>
<field1 name="foo">The value for the foo document</field1>
<field2 name="bar">The <value> for the <bar> document</field2>
</doc>
</root>
Wadą podejścia opartego na szablonach jest to, że nie dostaniesz ucieczki <
i >
za darmo. Tańczyłem wokół tego problemu, ściągając narzędzie zxml.sax
Właśnie skończyłem pisać generator XML, używając metody szablonów bigh_29 ... to dobry sposób na kontrolowanie tego, co generujesz, bez zbyt wielu obiektów przeszkadzających.
Jeśli chodzi o tag i wartość, użyłem dwóch tablic, jednej, która podawała nazwę i pozycję znacznika w wyjściowym pliku XML, a drugiej, która odwoływała się do pliku parametrów z tą samą listą tagów. Plik parametrów zawiera jednak również numer pozycji w odpowiednim pliku wejściowym (csv), z którego zostaną pobrane dane. W ten sposób, jeśli nastąpią jakiekolwiek zmiany w pozycji danych przychodzących z pliku wejściowego, program się nie zmieni; dynamicznie ustala pozycję pola danych z odpowiedniego tagu w pliku parametrów.