在使用 xml.etree.ElementTree 进行 XML 文档解析时,有时需要移除某些元素。如果您遇到以下情况:
- 有一棵 XML 树形结构,例如:
<metadata>
<lineage>
<srcinfo></srcinfo>
<procstep>
<otherinfo></otherinfo>
</procstep>
<procstep>
<otherinfo></otherinfo>
</procstep>
<procstep>
<otherinfo></otherinfo>
</procstep>
<procstep>
<otherinfo></otherinfo>
</procstep>
</lineage>
</metadata>
-
您需要删除第二个、第三个和第四个
procstep元素。 -
您尝试使用以下代码来完成此操作,但收到了 "ValueError: list.remove(x): x not in list" 错误:
while len(root.findall('.//lineage/procstep')) > 1:
root.remove(root.findall('.//lineage/procstep[last()]'))
2、解决方案
要解决这个问题,可以使用以下方法:
- 使用
ElementTree.iter()方法遍历lineage元素下的所有procstep元素:
for procstep in root.iter('procstep'):
# 检查该 `procstep` 元素是否是最后一个兄弟节点
if procstep.getnext() is None:
# 如果是,则从父节点中删除它
procstep.getparent().remove(procstep)
- 使用
ElementTree.find()方法查找最后一个procstep元素,然后将其从父节点中删除:
last_procstep = root.find('.//lineage/procstep[last()]')
last_procstep.getparent().remove(last_procstep)
- 使用
ElementTree.findall()方法查找所有procstep元素,然后倒序遍历它们,逐个删除:
for procstep in reversed(root.findall('.//lineage/procstep')):
procstep.getparent().remove(procstep)
代码例子
以下是一个完整的代码示例,演示了如何使用上述方法来删除 XML 文档中带有相同标签的最后一个兄弟节点:
import xml.etree.ElementTree as ET
xml_string = """
<metadata>
<lineage>
<srcinfo></srcinfo>
<procstep>
<otherinfo></otherinfo>
</procstep>
<procstep>
<otherinfo></otherinfo>
</procstep>
<procstep>
<otherinfo></otherinfo>
</procstep>
<procstep>
<otherinfo></otherinfo>
</procstep>
</lineage>
</metadata>
"""
root = ET.fromstring(xml_string)
# 方法 1:使用 ElementTree.iter() 方法遍历所有 procstep 元素
for procstep in root.iter('procstep'):
if procstep.getnext() is None:
procstep.getparent().remove(procstep)
# 方法 2:使用 ElementTree.find() 方法查找最后一个 procstep 元素并将其删除
last_procstep = root.find('.//lineage/procstep[last()]')
last_procstep.getparent().remove(last_procstep)
# 方法 3:使用 ElementTree.findall() 方法查找所有 procstep 元素并倒序遍历它们,逐个删除
for procstep in reversed(root.findall('.//lineage/procstep')):
procstep.getparent().remove(procstep)
print(ET.tostring(root, encoding='unicode'))
输出结果:
<metadata>
<lineage>
<srcinfo></srcinfo>
<procstep>
<otherinfo></otherinfo>
</procstep>
</lineage>
</metadata>
如您所见,使用上述方法可以正确地删除 XML 文档中带有相同标签的最后一个兄弟节点。