New submission from WoodyWoo <saulmatchless(a)163.com>:
We can remove elements using Element.remove(). Let’s say we want to remove all countries with a rank higher than 50:
>>>
>>> for country in root.findall('country'):
... rank = int(country.find('rank').text)
... if rank > 50:
... root.remove(country)
...
>>> tree.write('output.xml')
When the original xml has over 2 country with rank>50,and they are one by one neighborly siblings element,the upper code will delete the 1st 3rd 5th and more odd No. country.
A proper example should be:
index=0
while index < len(root.findall("./*")):
rank = int (root[index].find("rank").text)
if rank>50:
root.remove(root[index])
index=index+0
continue
index=index+1
I think "for each in list" should not work by index,but should work by pointer like thing,could be a list of pointers.
A finial solution should be like this --- when the "for each in list" was acting,the pointers list would be fixed,and you need not to worry about the "list" changing.
----------
assignee: docs@python
components: Documentation
messages: 377726
nosy: WoodyWoo, docs@python
priority: normal
severity: normal
status: open
title: Poor example for Element.remove()
type: behavior
versions: Python 3.8
_______________________________________
Python tracker <report(a)bugs.python.org>
<https://bugs.python.org/issue41899>
_______________________________________
WoodyWoo <saulmatchless(a)163.com> added the comment:
@eric.smith @scoder @serhiy.storchaka Thank U all.
I get what to do,and still think the "for in" structure should rebuilding.
All three methods:
import xml.etree.ElementTree as ET
xmlstr=\
r'''<?xml version="1.0"?>
<data>
<country name="Liechtenstein">
<rank updated="yes">2</rank>
<year>2008</year>
<gdppc>141100</gdppc>
<neighbor name="Austria" direction="E"/>
<neighbor name="Switzerland" direction="W"/>
</country>
<country name="Singapore">
<rank updated="yes">5</rank>
<year>2011</year>
<gdppc>59900</gdppc>
<neighbor name="Malaysia" direction="N"/>
</country>
<country name="Panama1">
<rank updated="yes">69</rank>
<year>2011</year>
<gdppc>13600</gdppc>
<neighbor name="Costa Rica" direction="W"/>
<neighbor name="Colombia" direction="E"/>
</country>
<country name="Panama2">
<rank updated="yes">69</rank>
<year>2011</year>
<gdppc>13600</gdppc>
<neighbor name="Costa Rica" direction="W"/>
<neighbor name="Colombia" direction="E"/>
</country>
</data>'''
print(xmlstr)
#orginal code
root = ET.fromstring(xmlstr)
for country in root.findall('country'):
rank = int(country.find('rank').text)
if rank > 50:
root.remove(country)
print("___orginal___")
for country in root.findall('country'):
print (country.get("name"))
print("^^^orginal^^^^\n")
#wrong code in my mind
root = ET.fromstring(xmlstr)
for country in root:
rank = int(country.find('rank').text)
if rank > 50:
root.remove(country)
print("___bad___")
for country in root.findall('country'):
print (country.get("name"))
print("^^^bad^^^^\n")
#my code
root = ET.fromstring(xmlstr)
index=0
count=len(root.findall("./*"))
while index <count:
rank = int (root[index].find("rank").text)
if rank>50:
root.remove(root[index])
index=index+0
count=count-1 # avoid index err
continue
index=index+1
print("___new___")
for country in root.findall('country'):
print (country.get("name"))
print("^^^new^^^^\n")
----------
_______________________________________
Python tracker <report(a)bugs.python.org>
<https://bugs.python.org/issue41892>
_______________________________________