web-dev-qa-db-fra.com

Meilleur moyen de générer du XML?

Je crée une API Web et j'ai besoin d'un bon moyen de générer très rapidement du XML bien formaté. Je ne trouve aucun moyen de le faire en python.

Remarque: Certaines bibliothèques semblent prometteuses mais manquent de documentation ou ne produisent que des fichiers. 

65
Joshkunz

Utiliser 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

Sortie:

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

Voir le tutorial pour plus d'informations.

86
ars

ElementTree est un bon module pour lire XML et écrire aussi, par exemple.

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

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

print tostring(root)

Sortie:

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

Voir ce tutorial pour plus de détails et comment bien imprimer.

Sinon, si votre XML est simple, ne sous-estimez pas la puissance du formatage de chaîne :)

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

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

Sortie:

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

Vous pouvez également utiliser string.Template ou un moteur de modèle pour la mise en forme complexe.

84
Anurag Uniyal

Je voudrais utiliser le yattag bibliothèque. Je pense que c'est la manière la plus pythonique:

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())
14

Utilisez la classe lxml.builder, à partir de: 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)

Sortie:

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

Un moyen optionnel si vous voulez utiliser du pur Python:

ElementTree est bon dans la plupart des cas, mais il ne peut pas CData et jolie impression.

Donc, si vous avez besoin de CData _ et de jolies lettres imprimées, vous devez utiliser minidom :

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>
9
SergO

J'ai essayé quelques-unes des solutions proposées dans ce fil de discussion et, malheureusement, j'ai trouvé certaines d'entre elles trop lourdes (c'est-à-dire nécessitant des efforts excessifs lorsque vous faites quelque chose de non trivial) et peu élégantes. En conséquence, je pensais que jetterais ma solution préférée, les objets d’aide HTML HTML , dans le mélange. 

Tout d’abord, installez le module web2py autonome :

pip install web2py

Malheureusement, ce qui précède installe une version extrêmement obsolète de web2py, mais cela suffira pour cet exemple. La source mise à jour est ici .

Importer des objets d'assistance HTML Web2py documentés ici .

from gluon.html import *

Maintenant, vous pouvez utiliser les assistants web2py pour générer du 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>
0
Boa