python - ejemplos - django
Creando un archivo XML simple usando python (5)
¿Cuáles son mis opciones si quiero crear un archivo XML simple en python? (sabio de la biblioteca)
El xml que quiero se ve así:
<root>
<doc>
<field1 name="blah">some value1</field1>
<field2 name="asdfasd">some vlaue2</field2>
</doc>
</root>
Hoy en día, la opción más popular (y muy simple) es la API ElementTree , que se ha incluido en la biblioteca estándar desde Python 2.5.
Las opciones disponibles para eso son:
- ElementTree (Implementación básica de Python puro de ElementTree. Parte de la biblioteca estándar desde 2.5)
- cElementTree (Implementación optimizada de C de ElementTree. También se ofrece en la biblioteca estándar desde 2.5)
- LXML (basado en libxml2. Ofrece un rico superconjunto de la API de ElementTree y XPath, selectores de CSS y más)
Aquí hay un ejemplo de cómo generar su documento de ejemplo usando in-stdlib cElementTree:
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 probé y funciona, pero supongo que el espacio 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 específica de LXML. No uso mucho la implementación de stdlib)
Para leer más, aquí hay algunos enlaces útiles:
- Documentos API para la implementación en la biblioteca estándar de Python
- Tutorial introductorio (del sitio original del autor)
- LXML etree tutorial . (Con código de ejemplo para cargar la mejor opción disponible de todas las implementaciones principales de ElementTree)
Como nota final, cElementTree o LXML deben ser lo suficientemente rápidos para todas sus necesidades (ambos son código C optimizado), pero en caso de que se encuentre en una situación en la que necesite exprimir hasta el último bit de rendimiento, los puntos de referencia en el sitio LXML indica que:
- LXML claramente gana para serializar (generar) XML
- Como efecto secundario de implementar un recorrido correcto de los padres, LXML es un poco más lento que cElementTree para el análisis sintáctico.
La biblioteca lxml incluye una sintaxis muy conveniente para la generación de XML, llamada E-factory . Así es como haré 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 agregar a un nodo ya hecho, por ejemplo, después de lo anterior podría decir
the_doc.append(FIELD2(''another value again'', name=''hithere''))
Para la opción más simple, iría con minidom: http://docs.python.org/library/xml.dom.minidom.html . Está integrado en la biblioteca estándar de Python y es sencillo de usar en casos simples.
Aquí hay un tutorial bastante fácil de seguir: http://www.boddie.org.uk/python/XML_intro.html
Para una estructura XML tan simple, es posible que no desee involucrar un módulo XML completo. 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 cadenas de python en bruto
Para un ejemplo de Jinja, vea mi respuesta a una pregunta similar .
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 <value> for the <bar> document</field2>
</doc>
</root>
La desventaja del enfoque de la plantilla es que no obtendrá escapes de <
y >
gratis. Bailé alrededor de ese problema tirando de un util de xml.sax
Yattag http://www.yattag.org/ o https://github.com/leforestier/yattag proporciona una API interesante para crear dicho documento XML (y también documentos HTML).
Está usando el administrador de contexto y with
palabra clave.
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)
entonces obtendrás:
<root>
<doc>
<field1 name="blah">some value1</field1>
<field2 name="asdfasd">some value2</field2>
</doc>
</root>