Home > Software design >  Why ElementTree.Element.remove() method is not working correctly with direct iteration?
Why ElementTree.Element.remove() method is not working correctly with direct iteration?

Time:04-21

I`m editing a XML file with Python xml.etree.ElementTree. Here is simple file example:

<root>
  <sub1>1</sub1>
  <sub2>2</sub2>
</root>

And I want to remove all root subelements. When I use

...
for child in root:
  root.remove(child)
...

'remove' method deletes only first subelement. But with

...
for child in root.getchildren():
  root.remove(child)
...

it works with all subelements. Why is this happening? Is it some iterator feature, or I need to know more about 'remove' method?

CodePudding user response:

Yes, it is an iterator if you use for child in root: And it is not recommended to remove item from its container using the iterator method. You should generate a list for your loop.

In your first remove operation (using an iterator), it actually remove all odd children (index 0, 2, 4, ..) and leave all even children in your root element. You can try the behaviour using a simple list:

l = [1,2,3,4,5,6]
for x in l:
    l.remove(x)
print (l)

It outputs

[2, 4, 6]

You can try it with your XML by adding a <sub3> element, and observe the similar result.

According to the official changelog here, the getchildren method is already deprecated.

It is suggested to use:

for child in list(root):
    # do something 
  • Related