tutorial library example etree dict create python xml-parsing iteration elementtree

library - python xml tutorial



ElementTree: Element.remove() iteraciĆ³n de salto (1)

Estás recorriendo el árbol en vivo:

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

que luego cambias mientras iteras. El ''contador'' de la iteración no será contado sobre el número cambiado de elementos, así que cuando se mira el elemento 0 y se elimina ese elemento, el iterador pasa al elemento número 1. Pero, ¿cuál era el elemento número 1? Ahora es el número del elemento 0.

Primero, capture una lista de todos los elementos y luego recorra eso:

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

.findall() devuelve una lista de resultados, que no se actualiza a medida que modifica el árbol.

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

>>> print ET.tostring(tree) <zero> <First> <second> <third-num>1</third-num> <third-def>object001</third-def> <third-len>458</third-len> </second> </First> </zero>

Este fenómeno no está limitado a los árboles de Element Tree; ver Bucle "Olvida" para eliminar algunos elementos

Tengo este archivo de entrada xml:

<?xml version="1.0"?> <zero> <First> <second> <third-num>1</third-num> <third-def>object001</third-def> <third-len>458</third-len> </second> <second> <third-num>2</third-num> <third-def>object002</third-def> <third-len>426</third-len> </second> <second> <third-num>3</third-num> <third-def>object003</third-def> <third-len>998</third-len> </second> </First> </zero>

Mi objetivo es eliminar cualquier segundo nivel para el que <third-def> 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 cualquier otro segundo nivel. Aquí está el resultado de este código:

<?xml version="1.0" ?> <zero> <First> <second> <third-num>1</third-num> <third-def>object001</third-def> <third-len>458</third-len> </second> <second> <third-num>3</third-num> <third-def>object003</third-def> <third-len>998</third-len> </second> </First> </zero>

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

<?xml version="1.0" ?> <zero> <First> <second> <third-num>1</third-num> <third-def>object001</third-def> <third-len>458</third-len> </second> <second/> <second/> </First> </zero>

¿Alguien tiene una pista de por qué mi declaración element.remove() es incorrecta?