我有一个特殊情况xml文件结构类似于:
<Root>
<parent1>
<parent2>
<element id="Something" >
</parent2>
</parent1>
<parent1>
<element id="Something">
</parent1>
</Root>
我的用例是删除重复的元素,我想删除具有相同Id的元素。我尝试了以下代码,没有任何积极的结果(它没有找到重复的节点)
import xml.etree.ElementTree as ET
path = 'old.xml'
tree = ET.parse(path)
root = tree.getroot()
prev = None
def elements_equal(e1, e2):
if type(e1) != type(e2):
return False
if e1.tag != e1.tag: return False
if e1.text != e2.text: return False
if e1.tail != e2.tail: return False
if e1.attrib != e2.attrib: return False
if len(e1) != len(e2): return False
return all([elements_equal(c1, c2) for c1, c2 in zip(e1, e2)])
for page in root: # iterate over pages
elems_to_remove = []
for elem in page:
for insideelem in page:
if elements_equal(elem, insideelem) and elem != insideelem:
print("found duplicate: %s" % insideelem.text) # equal function works well
elems_to_remove.append(insideelem)
continue
for elem_to_remove in elems_to_remove:
page.remove(elem_to_remove)
# [...]
tree.write("out.xml")
有人可以帮助我让我知道如何解决它。我对python很新,几乎没有经验。
答案 0 :(得分:1)
首先,您所做的是您正在使用的库中的一个难题,请参阅此问题:How to remove a node inside an iterator in python xml.etree.ElemenTree
解决方法是使用lxml
“实现相同的API但具有其他增强功能”。然后你可以做以下修复。
您似乎只遍历XML树中的第二级节点。你得到root
,然后带着孩子走路。这样您就可以从第一页获得parent2
,从第二页获得element
。此外,你不会在这里比较各页:
您的比较只会在同一页面中找到第二级重复项。
使用适当的遍历功能(例如iter
:
# Use a `set` to keep track of "visited" elements with good lookup time.
visited = set()
# The iter method does a recursive traversal
for el in root.iter('element'):
# Since the id is what defines a duplicate for you
if 'id' in el.attr:
current = el.get('id')
# In visited already means it's a duplicate, remove it
if current in visited:
el.getparent().remove(el)
# Otherwise mark this ID as "visited"
else:
visited.add(current)