220 votes

Création d'un simple fichier XML à l'aide de python

Quelles sont mes options pour créer un simple fichier XML en python (en fonction de la bibliothèque) ?

Le xml que je veux ressemble à ceci :

<root>
 <doc>
     <field1 name="blah">some value1</field1>
     <field2 name="asdfasd">some vlaue2</field2>
 </doc>

</root>

403voto

ssokolow Points 6549

Aujourd'hui, l'option la plus répandue (et la plus simple) est l'option API ElementTree , qui fait partie de la bibliothèque standard depuis Python 2.5.

Les options disponibles sont les suivantes :

  • ElementTree (Implémentation basique et purement Python de ElementTree. Fait partie de la bibliothèque standard depuis la version 2.5)
  • cElementTree (Implémentation C optimisée de ElementTree. Également proposé dans la bibliothèque standard depuis la version 2.5. Déclassé et intégré automatiquement dans ElementTree à partir de la version 3.3).
  • LXML (basé sur libxml2. Offre un riche surensemble de l'API ElementTree ainsi que XPath, les sélecteurs CSS, et plus encore)

Voici un exemple de la façon de générer votre document d'exemple en utilisant le cElementTree in-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")

Je l'ai testé et cela fonctionne, mais je suppose que les espaces blancs ne sont pas significatifs. Si vous avez besoin d'une indentation "jolie", faites-le moi savoir et je chercherai comment faire. (Il s'agit peut-être d'une option spécifique à LXML. Je n'utilise pas beaucoup l'implémentation stdlib)

Pour en savoir plus, voici quelques liens utiles :

Enfin, cElementTree ou LXML devraient être suffisamment rapides pour répondre à tous vos besoins (les deux sont du code C optimisé), mais si vous êtes dans une situation où vous avez besoin d'exploiter la moindre parcelle de performance, les benchmarks sur le site de LXML l'indiquent :

  • LXML l'emporte clairement pour la sérialisation (génération) de XML
  • Comme effet secondaire de l'implémentation de la traversée des parents, LXML est un peu plus lent que cElementTree pour l'analyse syntaxique.

0 votes

Je reçois import xml.etree.cElementTree as ET , ImportError: No module named etree.cElementTree - python standard OSX 10.8, mais il fonctionne lorsque je l'exécute depuis ipython.

1 votes

@Kasper : Je n'ai pas de Mac, je ne peux donc pas essayer de reproduire le problème. Indiquez-moi la version de Python et je verrai si je peux le reproduire sur Linux.

0 votes

@ssokolow, je suis sous OSX 10.9 maintenant et ce problème a été résolu d'une manière ou d'une autre, je ne me souviens pas si c'était ma propre action ou si j'ai fait quelque chose pour le résoudre.

78voto

rescdsk Points 4136

Les bibliothèque lxml comprend une syntaxe très pratique pour la génération de XML, appelée la syntaxe E-factory . Voici comment je ferais l'exemple que vous donnez :

#!/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)

Sortie :

<root>
  <doc>
    <field1 name="blah">some value1</field1>
    <field2 name="asdfasd">some value2</field2>
  </doc>
</root>

Il permet également d'ajouter des éléments à un nœud déjà créé, par exemple, après ce qui précède, vous pourriez dire

the_doc.append(FIELD2('another value again', name='hithere'))

3 votes

Si le nom de la balise n'est pas conforme aux règles d'identification de Python, vous pouvez utiliser getattr , par exemple, getattr(E, "some-tag") .

0 votes

Pour moi, print lxml.etree.tostring provoquait AttributeError : 'lxml.etree._Element' object has no attribute 'etree'. Cela fonctionnait sans commencer par "lxml" comme : etree.tostring(the_doc, pretty_print=True)

30voto

scls Points 379

Yattag http://www.yattag.org/ o https://github.com/leforestier/yattag fournit une API intéressante pour créer de tels documents XML (et aussi des documents HTML).

Il utilise gestionnaire de contexte y with mot-clé.

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)

vous obtiendrez donc :

<root>
    <doc>
        <field1 name="blah">some value1</field1>
        <field2 name="asdfasd">some value2</field2>
    </doc>
</root>

5voto

bigh_29 Points 126

Pour une structure XML aussi simple, il n'est peut-être pas nécessaire d'utiliser un module XML complet. Envisagez un modèle de chaîne pour les structures les plus simples, ou Jinja pour quelque chose d'un peu plus complexe. Jinja peut gérer le bouclage d'une liste de données pour produire le xml interne de votre liste de documents. C'est un peu plus délicat avec les modèles de chaînes en python brut

Pour un exemple en Jinja, voir mon réponse à une question similaire .

Voici un exemple de génération de votre xml avec des modèles de chaînes.

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

Sortie :

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

L'inconvénient de l'approche par modèle est que vous n'obtiendrez pas l'échappement de < y > gratuitement. J'ai contourné ce problème en faisant appel à un util de xml.sax

5voto

whaley Points 8789

Pour le choix le plus simple, je choisirais minidom : http://docs.python.org/library/xml.dom.minidom.html . Il est intégré à la bibliothèque standard de Python et est facile à utiliser dans les cas simples.

Voici un tutoriel assez facile à suivre : http://www.boddie.org.uk/python/XML_intro.html

21 votes

Cette réponse doit inclure un exemple d'utilisation du minidom.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X