从解析的XML树中删除元素会中断迭代
我想解析一个xml文件,然后通过删除所选元素来处理结果树.我的问题是删除一个元素会破坏迭代元素的循环.
考虑以下xml数据: <results> <group> <a /> <b /> <c /> </group> </results> 和代码: import xml.etree.ElementTree as ET def showGroup(group,s): print(s + ' len=' + str(len(group))) print('<group>' ) for e in group: print(' <' + e.tag + '>') print('</group>n') def processGroup(group): for e in group: if e.tag != 'a': group.remove(e) showGroup(group,'removed <' + e.tag + '>') tree = ET.parse('x.xml') root = tree.getroot() for group in root: processGroup(group) 我期望for循环处理元素< a>,< b>和< c>为了.尤其是: >处理< a>不应该删除任何元素 我希望生成的树在< group>内有一个元素. (< a>元素),len(组)将返回1. 相反,在处理< b>之后,for循环决定已经满足结束测试,并且它不处理元素< c>.如果是,则< c>将被删除.相反,我留下了一个元素< a>的树.和< c>,len(组)返回2. 在删除所选元素时,我需要做什么来处理所有三个元素? PS:欢迎任何关于风格的评论或更好的做事方式. 更新:如果在删除元素后没有代码,那么丑陋的黑客会以某种效率为代价“修复”问题.但在我的真实程序中,修剪循环后会有很多代码. for e in group: if e.tag != 'a': group.remove(e) showGroup(group,'removed <' + e.tag + '>') processGroup(group) 我假设如果for循环中断,那么在开始时再次启动组可能会解决问题.递归是一种整洁的方式 – 以重新处理已经检查但未被删除的所有元素为代价. 我对这个解决方案不满意.
问题是你正在从正在迭代的东西中删除元素,当你删除一个元素时,剩下的元素会被移位,所以你最终可能会删除不正确的元素:
一个简单的解决方案是遍历树的副本或使用反向: 复制: def processGroup(group): # creates a shallow copy so we are removing from the original # but iterating over a copy. for e in group[:]: if e.tag != 'a': group.remove(e) showGroup(group,'removed <' + e.tag + '>') 逆转: def processGroup(group): # starts at the end,as the container shrinks. # when an element is removed,we still see # elements at the same position when we started out loop. for e in reversed(group): if e.tag != 'a': group.remove(e) showGroup(group,'removed <' + e.tag + '>') 使用复制逻辑: In [7]: tree = ET.parse('test.xml') In [8]: root = tree.getroot() In [9]: for group in root: ...: processGroup(group) ...: removed <b> len=2 <group> <a> <c> </group> removed <c> len=1 <group> <a> </group> 您也可以使用ET.tostring代替for循环: import xml.etree.ElementTree as ET def show_group(group,s): print(s + ' len=' + str(len(group))) print(ET.tostring(group)) def process_group(group): for e in group[:]: if e.tag != 'a': group.remove(e) show_group(group,'removed <' + e.tag + '>') tree = ET.parse('test.xml') root = tree.getroot() for group in root.findall(".//group"): process_group(group) (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |