2009-02-03 13 views
10

Tengo el siguiente código.Python xml minidom. generar <text> Algunos texto</text> elemento

from xml.dom.minidom import Document 

doc = Document() 

root = doc.createElement('root') 
doc.appendChild(root) 
main = doc.createElement('Text') 
root.appendChild(main) 

text = doc.createTextNode('Some text here') 
main.appendChild(text) 

print doc.toprettyxml(indent='\t') 

El resultado es:

<?xml version="1.0" ?> 
<root> 
    <Text> 
     Some text here 
    </Text> 
</root> 

Esto es todo lo fino y elegante, pero lo que si quiero la salida a este aspecto?

<?xml version="1.0" ?> 
<root> 
    <Text>Some text here</Text> 
</root> 

¿Se puede hacer esto fácilmente?

Orjanp ...

+0

También me preguntaba esto, pero no estoy satisfecho con la respuesta aceptada, debido a usarlo tengo que instalar pxdom ... –

+0

Con la versión actual de xml.dom.minidom, que error está arreglado ahora – usethedeathstar

Respuesta

8

¿Puede esto fácilmente puede hacer?

Depende de la regla exacta que desee, pero en general no, tiene poco control sobre la impresión bonita. Si quiere un formato específico, generalmente tendrá que escribir su propio andador.

El DOM Nivel 3 LS-parámetro de formato agradable para la impresión en pxdom se acerca mucho a su ejemplo. Su regla es que si un elemento contiene un solo TextNode, no se agregará ningún espacio en blanco adicional. Sin embargo, (actualmente) utiliza dos espacios para una sangría en lugar de cuatro.

>>> doc= pxdom.parseString('<a><b>c</b></a>') 
>>> doc.domConfig.setParameter('format-pretty-print', True) 
>>> print doc.pxdomContent 
<?xml version="1.0" encoding="utf-16"?> 
<a> 
    <b>c</b> 
</a> 

(Ajuste de codificación y formato de salida para cualquier tipo de serialización que está haciendo.)

Si esa es la regla que desea, y usted puede salirse con la suya, también puede ser capaz de mono Element.writexml de minidom -patch, por ejemplo .:

>>> from xml.dom import minidom 
>>> def newwritexml(self, writer, indent= '', addindent= '', newl= ''): 
...  if len(self.childNodes)==1 and self.firstChild.nodeType==3: 
...   writer.write(indent) 
...   self.oldwritexml(writer) # cancel extra whitespace 
...   writer.write(newl) 
...  else: 
...   self.oldwritexml(writer, indent, addindent, newl) 
... 
>>> minidom.Element.oldwritexml= minidom.Element.writexml 
>>> minidom.Element.writexml= newwritexml 

Todas las advertencias habituales sobre la maldad de mono-parches se aplican.

+0

Gracias. ya que no voy a leer estos archivos de forma manual con tanta frecuencia, y esto no se hace fácilmente, supongo que lo dejo tal como está. Y enfoca mi atención a cosas más importantes, como hacer que funcione este load/save para xml. Orjanp ... – Orjanp

0

El paquete PyXML ofrece una solución simple a este mediante el uso de la función xml.dom.ext.PrettyPrint(). También puede imprimir en un descriptor de archivo.

Pero el paquete PyXML ya no se mantiene.

Oerjan Pettersen

2

que estaba buscando exactamente lo mismo, y me encontré con este aviso. (La sangría proporcionada en xml.dom.minidom rompió otra herramienta que estaba usando para manipular el XML, y yo necesitaba para tener una sangría) Probé la solución aceptada con un ejemplo un poco más complejo y este fue el resultado:

In [1]: import pxdom 

In [2]: xml = '<a><b>fda</b><c><b>fdsa</b></c></a>' 

In [3]: doc = pxdom.parseString(xml) 

In [4]: doc.domConfig.setParameter('format-pretty-print', True) 

In [5]: print doc.pxdomContent 
<?xml version="1.0" encoding="utf-16"?> 
<a> 
    <b>fda</b><c> 
    <b>fdsa</b> 
    </c> 
</a> 

El bonito XML impreso no está formateado correctamente, y no estoy muy contento con el parche mono (es decir, apenas sé lo que significa, y entiendo que es malo), así que busqué otra solución.

estoy escribiendo la salida a un archivo, por lo que puede utilizar el programa xmlindent para Ubuntu ($ sudo aptitude install xmlindent). Por lo que acaba de escribir el formateado en el fichero, a continuación, llamar a la xmlindent desde el programa Python:

from subprocess import Popen, PIPE 
Popen(["xmlindent", "-i", "2", "-w", "-f", "-nbe", file_name], 
     stderr=PIPE, 
     stdout=PIPE).communicate() 

La opción -w hace que el archivo se sobrescriba, pero molesto deja una llamada, por ejemplo, "myfile.xml ~" que probablemente quiera eliminar.Los otros interruptores están ahí para obtener el formato correcto (para mí).

P.S. xmlindent es un formateador de flujo, es decir, se puede utilizar de la siguiente manera:

cat myfile.xml | xmlindent > myfile_indented.xml 

lo que podría ser capaz de utilizarlo en un script en Python, sin necesidad de escribir en un archivo si necesita.

0

Esta solución funcionó para mí sin parches mono o dejar de usar minidom:

from xml.dom.ext import PrettyPrint 
from StringIO import StringIO 

def toprettyxml_fixed (node, encoding='utf-8'): 
    tmpStream = StringIO() 
    PrettyPrint(node, stream=tmpStream, encoding=encoding) 
    return tmpStream.getvalue() 

http://ronrothman.com/public/leftbraned/xml-dom-minidom-toprettyxml-and-silly-whitespace/#best-solution

+0

Sí, esta solución ya se menciona aquí. Pero si no me equivoco, esta solución requiere la instalación de pyxml. Pyxml parece no estar actualizado en este momento. Entonces creo que una solución diferente es mejor, como lxml. http://stackoverflow.com/questions/507405/python-xml-minidom-generate-textsome-text-text-element/623868#623868 – Orjanp

1

Esto podría hacerse con toxml(), el uso de expresiones regulares a lo ordenado.

>>> from xml.dom.minidom import Document 
>>> import re 
>>> doc = Document() 
>>> root = doc.createElement('root') 
>>> _ = doc.appendChild(root) 
>>> main = doc.createElement('Text') 
>>> _ = root.appendChild(main) 
>>> text = doc.createTextNode('Some text here') 
>>> _ = main.appendChild(text) 
>>> out = doc.toxml() 
>>> niceOut = re.sub(r'><', r'>\n<', re.sub(r'(<\/.*?>)', r'\1\n', out)) 
>>> print niceOut 
<?xml version="1.0" ?> 
<root> 
<Text>Some text here</Text> 
</root> 
0

La manera más fácil de hacer esto es usar prettyxml, y eliminar el \ n y \ t dentro de las etiquetas. De esa manera, mantendrá su sangría como lo requirió en su ejemplo.

xml_output = doc.toprettyxml() nojunkintags = re.sub('>(\n|\t)</', '', xml_output) print nojunkintags

Cuestiones relacionadas