Лучший способ для создания xml? [дубликат]


этот вопрос уже есть ответ здесь:

Я создаю веб-API и нужен хороший способ быстро создать хорошо сформированный XML. Я не могу найти хороший способ сделать это в Python.

Примечание: некоторые библиотеки выглядят многообещающе, но либо отсутствие документации или только вывод в файлы.

6 63

6 ответов:

используя lxml:

from lxml import etree

# create XML 
root = etree.Element('root')
root.append(etree.Element('child'))
# another child with text
child = etree.Element('child')
child.text = 'some text'
root.append(child)

# pretty string
s = etree.tostring(root, pretty_print=True)
print s

выход:

<root>
  <child/>
  <child>some text</child>
</root>

посмотреть учебник для получения дополнительной информации.

ElementTree это хороший модуль для чтения xml и записи тоже например

from xml.etree.ElementTree import Element, SubElement, tostring

root = Element('root')
child = SubElement(root, "child")
child.text = "I am a child"

print tostring(root)

выход:

<root><child>I am a child</child></root>

посмотреть этот учебник для получения более подробной информации и как довольно печати.

альтернативно, если ваш XML прост, не стоит недооценивать силу форматирования строк:)

xmlTemplate = """<root>
    <person>
        <name>%(name)s</name>
        <address>%(address)s</address>
     </person>
</root>"""

data = {'name':'anurag', 'address':'Pune, india'}
print xmlTemplate%data

выход:

<root>
    <person>
        <name>anurag</name>
        <address>Pune, india</address>
     </person>
</root>

вы можете использовать string.Шаблон или какой-то шаблонный движок тоже, для сложного форматирования.

использовать lxml.класс строителя, от:http://lxml.de/tutorial.html#the-e-factory

import lxml.builder as lb
from lxml import etree

nstext = "new story"
story = lb.E.Asset(
  lb.E.Attribute(nstext, name="Name", act="set"),
  lb.E.Relation(lb.E.Asset(idref="Scope:767"),
            name="Scope", act="set")
  )

print 'story:\n', etree.tostring(story, pretty_print=True)

выход:

story:
<Asset>
  <Attribute name="Name" act="set">new story</Attribute>
  <Relation name="Scope" act="set">
    <Asset idref="Scope:767"/>
  </Relation>
</Asset>

Я бы использовал yattag библиотека. Я думаю, что это самый питонический способ:

from yattag import Doc

doc, tag, text = Doc().tagtext()

with tag('food'):
    with tag('name'):
        text('French Breakfast')
    with tag('price', currency='USD'):
        text('6.95')
    with tag('ingredients'):
        for ingredient in ('baguettes', 'jam', 'butter', 'croissants'):
            with tag('ingredient'):
                text(ingredient)


print(doc.getvalue())

дополнительный способ, если вы хотите использовать чистый Python:

ElementTree хорошо для большинства случаев, но это не может CData и печати.

Итак, если вам нужно CData и печати вы должны использовать минидом:

minidom_example.py:

from xml.dom import minidom

doc = minidom.Document()

root = doc.createElement('root')
doc.appendChild(root)

leaf = doc.createElement('leaf')
text = doc.createTextNode('Text element with attributes')
leaf.appendChild(text)
leaf.setAttribute('color', 'white')
root.appendChild(leaf)

leaf_cdata = doc.createElement('leaf_cdata')
cdata = doc.createCDATASection('<em>CData</em> can contain <strong>HTML tags</strong> without encoding')
leaf_cdata.appendChild(cdata)
root.appendChild(leaf_cdata)

branch = doc.createElement('branch')
branch.appendChild(leaf.cloneNode(True))
root.appendChild(branch)

mixed = doc.createElement('mixed')
mixed_leaf = leaf.cloneNode(True)
mixed_leaf.setAttribute('color', 'black')
mixed_leaf.setAttribute('state', 'modified')
mixed.appendChild(mixed_leaf)
mixed_text = doc.createTextNode('Do not use mixed elements if it possible.')
mixed.appendChild(mixed_text)
root.appendChild(mixed)

xml_str = doc.toprettyxml(indent="  ")
with open("minidom_example.xml", "w") as f:
    f.write(xml_str)

minidom_example.XML-код:

<?xml version="1.0" ?>
<root>
  <leaf color="white">Text element with attributes</leaf>
  <leaf_cdata>
<![CDATA[<em>CData</em> can contain <strong>HTML tags</strong> without encoding]]>  </leaf_cdata>
  <branch>
    <leaf color="white">Text element with attributes</leaf>
  </branch>
  <mixed>
    <leaf color="black" state="modified">Text element with attributes</leaf>
    Do not use mixed elements if it possible.
  </mixed>
</root>

Я пробовал некоторые решения в этой теме, и, к сожалению, я нашел некоторые из них громоздкими (т. е. требующими чрезмерных усилий при выполнении чего-то нетривиального) и неэлегантными. Следовательно, я думал, что брошу свое предпочтительное решение,web2py HTML helper objects, в миксе.

во-первых, установите the автономный модуль web2py:

pip install web2py

к сожалению, выше устанавливается чрезвычайно устаревшая версия web2py, но это будет достаточно хорошо для этого примера. Обновленный источник здесь.

импорт web2py HTML вспомогательные объекты документированы здесь.

from gluon.html import *

Теперь вы можете использовать помощники web2py для создания XML/HTML.

words = ['this', 'is', 'my', 'item', 'list']
# helper function
create_item = lambda idx, word: LI(word, _id = 'item_%s' % idx, _class = 'item')
# create the HTML
items = [create_item(idx, word) for idx,word in enumerate(words)]
ul = UL(items, _id = 'my_item_list', _class = 'item_list')
my_div = DIV(ul, _class = 'container')

>>> my_div

<gluon.html.DIV object at 0x00000000039DEAC8>

>>> my_div.xml()
# I added the line breaks for clarity
<div class="container">
   <ul class="item_list" id="my_item_list">
      <li class="item" id="item_0">this</li>
      <li class="item" id="item_1">is</li>
      <li class="item" id="item_2">my</li>
      <li class="item" id="item_3">item</li>
      <li class="item" id="item_4">list</li>
   </ul>
</div>