Ответы:
В наши дни наиболее популярным (и очень простым) вариантом является API ElementTree , который был включен в стандартную библиотеку начиная с Python 2.5.
Доступные варианты для этого:
Вот пример того, как сгенерировать ваш пример документа с использованием in-stdlib cElementTree:
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")
Я проверил это, и оно работает, но я предполагаю, что пробелы не имеют существенного значения. Если вам нужен отступ "prettyprint", дайте мне знать, и я посмотрю, как это сделать. (Это может быть специфичная для LXML опция. Я не очень часто использую реализацию stdlib)
Для дальнейшего чтения вот несколько полезных ссылок:
В заключение отметим, что cElementTree или LXML должны быть достаточно быстрыми для всех ваших потребностей (оба оптимизированных кода C), но в случае, если вам нужно выжать все до последней черты производительности, тесты производительности сайт LXML указывает, что:
xml_declaration=True
если вы задаете кодировку ... но, чтобы получить эквивалентное поведение, вызовите tree.write()
так: tree.write("filename.xml", xml_declaration=True, encoding='utf-8')
Вы можете использовать любую кодировку, если вы явно укажете один. ( ascii
принудительно закодирует все символы Unicode за пределами 7-битного набора ASCII, если вы не доверяете правильной настройке веб-сервера.)
vlaue2
на value2
: опечатка в запрашиваемом выводе XML в исходном вопросе. До этого изменения, опечатка здесь на самом деле не является правильной.
cElementTree
был объявлен
Библиотека lxml включает в себя очень удобный синтаксис для генерации XML, называемый E-factory . Вот как я приведу пример, который вы приводите:
#!/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)
Вывод:
<root>
<doc>
<field1 name="blah">some value1</field1>
<field2 name="asdfasd">some value2</field2>
</doc>
</root>
Он также поддерживает добавление к уже созданному узлу, например, после вышесказанного можно сказать
the_doc.append(FIELD2('another value again', name='hithere'))
getattr
, например, getattr(E, "some-tag")
.
Yattag http://www.yattag.org/ или https://github.com/leforestier/yattag предоставляет интересный API для создания такого XML-документа (а также HTML-документов).
Он использует менеджер контекста и with
ключевое слово.
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)
так вы получите:
<root>
<doc>
<field1 name="blah">some value1</field1>
<field2 name="asdfasd">some value2</field2>
</doc>
</root>
Для простейшего выбора я бы выбрал минидом: http://docs.python.org/library/xml.dom.minidom.html . Он встроен в стандартную библиотеку Python и прост в использовании в простых случаях.
Вот довольно простой учебник: http://www.boddie.org.uk/python/XML_intro.html
Для такой простой XML-структуры вы можете не использовать полноценный XML-модуль. Рассмотрим строковый шаблон для простейших структур или Jinja для чего-то более сложного. Jinja может обрабатывать циклы по списку данных для создания внутреннего XML-списка вашего документа. Это немного сложнее с необработанными шаблонами строк Python
Для примера Jinja, см. Мой ответ на аналогичный вопрос .
Вот пример создания вашего xml с помощью строковых шаблонов.
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
Вывод:
<root>
<doc>
<field1 name="foo">The value for the foo document</field1>
<field2 name="bar">The <value> for the <bar> document</field2>
</doc>
</root>
Недостатком шаблонного подхода является то, что вы не сможете избежать <
и >
бесплатно. Я танцевал вокруг этой проблемы, вытаскивая утилиту изxml.sax
Я только что закончил писать генератор xml, используя метод шаблонов bigh_29 ... это хороший способ контролировать то, что вы выводите без слишком большого количества объектов, попадающих «в пути».
Что касается тега и значения, я использовал два массива, один из которых давал имя и позицию тега в выходном xml, а другой - ссылку на файл параметров, содержащий тот же список тегов. Файл параметров, однако, также имеет номер позиции в соответствующем файле ввода (CSV), откуда данные будут взяты. Таким образом, если есть какие-либо изменения в положении данных, поступающих из входного файла, программа не изменится; он динамически определяет положение поля данных из соответствующего тега в файле параметров.