2010-08-31 5 views

ответ

190

В эти дни, наиболее популярны (и очень простой) вариант является ElementTree API, , который был включен в стандартную библиотеку с Python 2.5.

Доступные варианты для этого являются:

  • ElementTree (Basic, реализация чистого питон ElementTree части стандартной библиотеки, так как 2.5.)
  • cElementTree (оптимизированная реализация C из ElementTree Также предлагаются. стандартная библиотека начиная с 2.5)
  • LXML (на основе libxml2. Он предлагает богатый надмножество API ElementTree, а также в XPath, CSS селекторы, и больше)

Вот пример того, как сгенерировать пример документа с помощью cElementTree в-STDLIB:

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 показывают, что:

  • LXML явно выигрывает для сериализации (генераторный) XML
  • Как побочного эффект реализации правильного обхода родителя, LXML немного медленнее, чем cElementTree для синтаксического анализа.
+0

Я получаю 'import xml.etree.cElementTree как ET',' ImportError: Нет модуля с именем etree.cElementTree' - стандартный OSX 10.8 python, но как-то он работает, когда я запускаю его изнутри ipython. – guaka

+1

@ Kasper: У меня нет Mac, поэтому я не могу попытаться дублировать проблему. Скажите мне версию Python, и я посмотрю, смогу ли я ее воспроизвести в Linux. – ssokolow

+0

@ssokolow, я сейчас на OSX 10.9, и это как-то было разрешено, я не помню, было ли это мое собственное действие или я сделал что-то, чтобы его разрешить. – guaka

5

Для простейшего выбора, я бы с minidom: http://docs.python.org/library/xml.dom.minidom.html. Он встроен в стандартную библиотеку python и прост в использовании в простых случаях.

Вот довольно легко следовать учебник: http://www.boddie.org.uk/python/XML_intro.html

+0

Этот ответ должен включать пример использования мини-диска. –

46

lxml library включает в себя очень удобный синтаксис для генерации 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')) 
+1

Если имя тега не соответствует к правилам идентификатора Python, тогда вы можете использовать 'getattr', например,' getattr (E, "some-tag") '. – haridsv

9

Yattag http://www.yattag.org/ или https://github.com/leforestier/yattag дает интересный API для создания такого XML-документа (а также HTML-документы).

Используется context manager и 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> 
0

Для такой простой структуры XML, вы не можете включать в себя полноценную модуль X. Рассмотрим шаблон строки для простейших структур, или Jinja для чего-то более сложного. Jinja может обрабатывать переплетение списка данных для создания внутреннего xml вашего списка документов. Это немного сложнее с необработанными шаблонами строк python

Для примера Jinja см. Мой answer to a similar question.

Вот пример генерации вашего 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 &lt;value&gt; for the &lt;bar&gt; document</field2> 
</doc> 
</root> 

неудачник матричного подхода заключается в том, что вы не получите спасаясь от < и > бесплатно. Я танцевал вокруг этой проблемы, потянув в утилиту от xml.sax

Смежные вопросы