2010-08-31 27 views
95

¿Cuáles son mis opciones si quiero crear un archivo XML simple en python? (Biblioteca en cuanto a)Creando un archivo XML simple usando python

el XML que quiero es así:

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

</root> 

Respuesta

190

En estos días, la opción más popular (y muy simple) es la ElementTree API, que ha sido incluido en la biblioteca estándar desde Python 2.5.

Las opciones disponibles para que son:

  • elementtree (básico, aplicación pura en Python de elementtree parte de la biblioteca estándar desde 2.5.)
  • cElementTree (Optimized aplicación C de elementtree también ofrecido en. la biblioteca estándar desde 2,5)
  • LXML (Basado en libxml2. ofrece una rica superconjunto de la API elementtree así XPath, CSS selectores, y más)

He aquí un ejemplo de cómo generar el documento de ejemplo utilizando el cElementTree en 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") 

Lo he probado y funciona, pero estoy suponiendo que los espacios en blanco no es significativo. Si necesita una sangría de "impresión bonita", hágamelo saber y buscaré cómo hacerlo. (. Puede ser una opción-LXML específica Yo no uso la aplicación stdlib mucho)

Para leer más, aquí hay algunos enlaces útiles:

Como nota final, ya sea cElementTree o LXML debe ser lo suficientemente rápido para todas sus necesidades (tanto están optimizados código C), pero en el evento que estás en una situación en la que necesita para exprimir hasta la última gota de rendimiento, los puntos de referencia en el sitio LXML indican que:

  • LXML gana claramente para serializar (generador) XML
  • Como lado- El efecto de implementar un recorrido correcto de los padres, LXML es un poco más lento que cElementTree para el análisis sintáctico.
+0

Obtengo 'import xml.etree.cElementTree como ET',' ImportError: No module named etree.cElementTree' - estándar OSX 10.8 python, pero de alguna manera funciona cuando lo ejecuto desde dentro de ipython. – guaka

+1

@Kasper: no tengo una Mac así que no puedo intentar duplicar el problema. Cuéntame la versión de Python y veré si puedo replicarla en Linux. – ssokolow

+0

@ssokolow, estoy en OSX 10.9 ahora y esto de alguna manera se ha resuelto, no recuerdo si fue por mi propia acción o si hice algo para resolverlo. – guaka

46

El lxml library incluye una sintaxis muy conveniente para la generación de XML, llamado el E-factory.Así es como lo haría el ejemplo que das:

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

Salida:

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

También es compatible con la adición de un nodo ya hecha, por ejemplo, después de lo anterior se podría decir

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

Si el nombre de la etiqueta no se ajusta a las reglas de identificador de Python, entonces podría usar 'getattr', por ejemplo,' getattr (E, "some-tag") '. – haridsv

9

Yattag http://www.yattag.org/ o https://github.com/leforestier/yattag proporciona una API para crear interesantes como documento XML (y también los documentos HTML).

Está utilizando la palabra clave context manager y 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) 

por lo que obtendrá:

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

Para una estructura XML tan simple, puede que no quiera involucrar a un módulo completo XML soplado. Considere una plantilla de cadena para las estructuras más simples, o Jinja para algo un poco más complejo. Jinja puede manejar el bucle sobre una lista de datos para producir el xml interno de su lista de documentos. Eso es un poco más complicado con las plantillas de cadena de python en bruto

Para un ejemplo de Jinja, vea mi answer to a similar question.

Aquí hay un ejemplo de generación de su xml con plantillas de cadena.

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 

Salida:

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

La decepción del enfoque de la plantilla es que no se va a escapar de < y > de forma gratuita. Bailé alrededor de ese problema al conectar un utilizador desde xml.sax

Cuestiones relacionadas