Respuestas:
En estos días, 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:
Aquí hay un ejemplo de cómo generar su documento de ejemplo usando 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 probé y funciona, pero supongo que el espacio en blanco no es significativo. Si necesita una sangría de "impresión bonita", avíseme 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:
Como nota final, cElementTree o LXML deben ser lo suficientemente rápidos para todas sus necesidades (ambos son código C optimizado), pero en el 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:
xml_declaration=True
si especifica una codificación ... pero, para obtener un comportamiento equivalente, llame de tree.write()
esta manera: tree.write("filename.xml", xml_declaration=True, encoding='utf-8')
puede usar cualquier codificación siempre que especifique explícitamente uno. ( ascii
forzará que todos los caracteres Unicode fuera del conjunto ASCII de 7 bits se codifiquen por entidad si no confía en que un servidor web esté configurado correctamente.)
vlaue2
a value2
: El error tipográfico se encuentra en la salida XML solicitada en la pregunta original. Hasta que eso cambie, el error tipográfico aquí en realidad es correcto.
cElementTree
se depreció en Python 3.3
La biblioteca lxml incluye una sintaxis muy conveniente para la generación de XML, llamada E-factory . Así es como 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 admite 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'))
getattr
, por ejemplo, getattr(E, "some-tag")
.
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 la 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>
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 fácil 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 sin procesar
Para un ejemplo de Jinja, vea mi respuesta a una pregunta similar .
Aquí hay un ejemplo de cómo generar 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 decepción de la plantilla de enfoque es que no se va a escapar de <
y >
de forma gratuita. Bailé alrededor de ese problema sacando una utilidad dexml.sax
Acabo de terminar de escribir un generador xml, utilizando el método de Plantillas de bigh_29 ... es una buena manera de controlar lo que se genera sin que demasiados Objetos se interpongan en el camino.
En cuanto a la etiqueta y el valor, utilicé dos matrices, una que daba el nombre y la posición de la etiqueta en la salida xml y otra que hacía referencia a un archivo de parámetros que tenía la misma lista de etiquetas. Sin embargo, el archivo de parámetros también tiene el número de posición en el archivo de entrada (csv) correspondiente de donde se tomarán los datos. De esta manera, si hay algún cambio en la posición de los datos provenientes del archivo de entrada, el programa no cambia; calcula dinámicamente la posición del campo de datos a partir de la etiqueta apropiada en el archivo de parámetros.