Cómo eliminar elementos de XML usando Python

Me quedé atascado con XML y Python. La tarea es simple, pero no pude resolverla hasta el momento y la dediqué tanto tiempo. Vine aquí por un consejo sobre cómo resolverlo con un par de líneas.

Gracias por cualquier ayuda para atravesar el árbol. Siempre terminé con demasiados o muy pocos elementos. Los elementos se pueden anidar sin límite. El ejemplo dado es solo un ejemplo. Aceptaré cualquier solución, no exigente acerca de dom, minidom, sax, lo que sea ..

Tengo un archivo XML similar a este:

  Common content  Content EN žluťoučký koníček  Common content Content EN Content CS  Content EN Content EN   Content CS Content CS    

Lo que necesito – analizar el XML y escribir un nuevo archivo. El nuevo archivo debe contener todos los elementos para un idioma dado y elementos sin atributo lang .

Para el lenguaje “cs”, el archivo de salida debe contener esto:

   Common content  žluťoučký koníček  Common content Content CS  Content CS Content CS    

Si puede hacerlo para omitir el atributo lang en el nuevo archivo, aún mejor. Pero no es tan importante.

ACTUALIZACIÓN1: Se agregaron caracteres Unicode y atributo de espacio de nombres.

ACTUALIZACIÓN2: Usando Python 2.5, se prefieren las bibliotecas estándar.

Usando lxml :

 import lxml.etree as le with open('doc.xml','r') as f: doc=le.parse(f) for elem in doc.xpath('//*[attribute::lang]'): if elem.attrib['lang']=='en': elem.attrib.pop('lang') else: parent=elem.getparent() parent.remove(elem) print(le.tostring(doc)) 

rendimientos

  Common content  Content EN  Common content Content EN  Content EN Content EN   

No estoy seguro de cuál es la mejor forma de eliminar el atributo lang , pero aquí hay un código que hace los otros cambios (Python 2.7; para 2.5 o 2.6, use getIterator lugar de iter ), asumiendo que cuando elimine un elemento que siempre desea remover todo lo contenido en ese elemento.

Este código simplemente imprime el resultado a la salida estándar (puede redirigirlo como desee, por supuesto, o escribirlo directamente en algún archivo nuevo, etc.):

 import sys from xml.etree import cElementTree as et def picklang(path, lang='en'): tr = et.parse(path) for element in tr.iter(): for subelement in element: la = subelement.get('lang') if la is not None and la != lang: element.remove(subelement) return tr if __name__ == '__main__': tr = picklang('la.xml') tr.write(sys.stdout) print 

Con la.xml siendo tu ejemplo, esto escribe

  Common content  Content EN  Common content Content EN  Content EN Content EN   

actualizando el código de @Alex Martelli para eliminar un error donde la lista de elementos se actualiza en su lugar. La solución anterior dará una respuesta incorrecta si la entrada es un poco más compleja.

 import sys from xml.etree import cElementTree as et def picklang(path, lang='en'): tr = et.parse(path) for element in tr.iter(): for subelement in element[:]: la = subelement.get('lang') if la is not None and la != lang: element.remove(subelement) return tr if __name__ == '__main__': tr = picklang('la.xml') tr.write(sys.stdout) print 

El código en la línea 7 for subelement in element: se cambia a for subelement in element[:]: ya que es incorrecto actualizar la lista en su lugar mientras se está iterando sobre ella.

Este código recorre una copia de la lista de elementos y elimina elementos cuando lang! = “En” en la lista de elementos original.