ElementTree: Element.remove () saltar iteración

Tengo este archivo de entrada xml:

    1 object001 458   2 object002 426   3 object003 998    

Mi objective es eliminar cualquier segundo nivel para el que no sea un valor. Para hacer eso, escribí este código:

 try: import xml.etree.cElementTree as ET except ImportError: import xml.etree.ElementTree as ET inputfile='inputfile.xml' tree = ET.parse(inputfile) root = tree.getroot() elem = tree.find('First') for elem2 in tree.iter(tag='second'): if elem2.find('third-def').text == 'object001': pass else: elem.remove(elem2) #elem2.clear() 

Mi problema es elem.remove(elem2) . Se salta cada segundo nivel. Aquí está la salida de este código:

     1 object001 458   3 object003 998    

Ahora, si elem2.clear() el comentario de la línea elem2.clear() , el script funciona perfectamente, pero la salida es menos agradable ya que mantiene todos los segundos niveles eliminados:

     1 object001 458      

¿Alguien tiene una pista de por qué mi statement element.remove() está mal?

Estás haciendo un bucle sobre el árbol vivo:

 for elem2 in tree.iter(tag='second'): 

que luego cambias mientras iteras. El ‘contador’ de la iteración no recibirá información sobre el número cambiado de elementos, por lo que al mirar el elemento 0 y eliminar ese elemento, el iterador pasa al elemento número 1. Pero lo que era el elemento número 1 ahora es el elemento número 0.

Capture primero una lista de todos los elementos, luego haga un bucle sobre eso:

 for elem2 in tree.findall('.//second'): 

.findall() devuelve una lista de resultados, que no se actualiza al modificar el árbol.

Ahora la iteración no saltará el último elemento:

 >>> print ET.tostring(tree)    1 object001 458    

Este fenómeno no se limita a los árboles ElementTree; ver Bucle “Olvida” para eliminar algunos elementos