Python cómo quitar los espacios en blanco de los nodos de texto xml

Tengo un archivo xml de la siguiente manera

  My Name  
My Address

La etiqueta tiene nuevas líneas adicionales. ¿Hay alguna forma rápida en Pythonic para recortar esto y generar un nuevo xml?

Encontré esto pero recorta solo lo que está entre las tags y no el valor https://skyl.org/log/post/skyl/2010/04/remove-insignificant-whitespace-from-xml-string-with-python/

Actualización 1 – Manejar el siguiente xml que tiene espacios de cola en la etiqueta

   My NameMy  
My Address

Manejador de respuesta aceptado por encima de ambos tipos de XML

Actualización 2: he publicado mi versión en la respuesta a continuación, la estoy usando para eliminar todo tipo de espacios en blanco y generar un bonito XML en un archivo con codificaciones XML.

https://stackoverflow.com/a/19396130/973699

Con lxml puedes iterar sobre todos los elementos y verificar si tiene texto para strip() :

 from lxml import etree tree = etree.parse('xmlfile') root = tree.getroot() for elem in root.iter('*'): if elem.text is not None: elem.text = elem.text.strip() print(etree.tostring(root)) 

Cede:

 My Name 
My Address

ACTUALIZACIÓN para quitar el texto de la tail también:

 from lxml import etree tree = etree.parse('xmlfile') root = tree.getroot() for elem in root.iter('*'): if elem.text is not None: elem.text = elem.text.strip() if elem.tail is not None: elem.tail = elem.tail.strip() print(etree.tostring(root, encoding="utf-8", xml_declaration=True)) 

La respuesta aceptada dada por Birei usando lxml hace el trabajo perfectamente, pero quería recortar todo tipo de espacios en blanco / en blanco, líneas en blanco y regenerar bastante XML en un archivo xml.

Siguiendo el código hice lo que quería

 from lxml import etree #discard strings which are entirely white spaces myparser = etree.XMLParser(remove_blank_text=True) root = etree.parse('xmlfile',myparser) #from Birei's answer for elem in root.iter('*'): if elem.text is not None: elem.text = elem.text.strip() if elem.tail is not None: elem.tail = elem.tail.strip() #write the xml file with pretty print and xml encoding root.write('xmlfile', pretty_print=True, encoding="utf-8", xml_declaration=True) 

Tiene que hacer un análisis xml de una u otra manera, así que tal vez use xml.sax y cópielo en la secuencia de salida en cada evento (omitiendo el xml.sax ignorableWhitespace ), y agregue marcadores de tags según sea necesario. Consulte el código de muestra aquí http://www.knowthytools.com/2010/03/sax-parsing-with-python.html .

Puedes usar beautifulsoup . Recorra todos los elementos y, para cada uno que contenga algún texto, reemplácelo con su versión reducida:

 from bs4 import BeautifulSoup soup = BeautifulSoup(open('xmlfile', 'r'), 'xml') for elem in soup.find_all(): if elem.string is not None: elem.string = elem.string.strip() print(soup) 

Suponiendo que xmlfile con el contenido proporcionado en la pregunta, se obtiene:

   My Name 
My Address

Estoy trabajando con una versión anterior de Python (2.3), y actualmente estoy atascado con la biblioteca estándar. Para mostrar una respuesta que es muy compatible con versiones anteriores, escribí esto con las funciones xml.dom y xml.minidom .

 import codecs from xml.dom import minidom # Read in the file to a DOM data structure. original_document = minidom.parse("original_document.xml") # Open a UTF-8 encoded file, because it's fairly standard for XML. stripped_file = codecs.open("stripped_document.xml", "w", encoding="utf8") # Tell minidom to format the child text nodes without any extra whitespace. original_document.writexml(stripped_file, indent="", addindent="", newl="") stripped_file.close() 

Si bien no es BeautifulSoup , esta solución es bastante elegante y utiliza toda la fuerza de la API de nivel inferior. Tenga en cuenta que el formato real es solo una línea 🙂

Documentación de las llamadas API utilizadas aquí:

  • minidom.parse
  • minidom.Node.writexml
  • codecs.open