在 XML 文档中删除带有相同标签的最后一个兄弟节点

125 阅读1分钟

在使用 xml.etree.ElementTree 进行 XML 文档解析时,有时需要移除某些元素。如果您遇到以下情况:

huake_00063_.jpg

  • 有一棵 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、解决方案

要解决这个问题,可以使用以下方法:

  1. 使用 ElementTree.iter() 方法遍历 lineage 元素下的所有 procstep 元素:
for procstep in root.iter('procstep'):
    # 检查该 `procstep` 元素是否是最后一个兄弟节点
    if procstep.getnext() is None:
        # 如果是,则从父节点中删除它
        procstep.getparent().remove(procstep)
  1. 使用 ElementTree.find() 方法查找最后一个 procstep 元素,然后将其从父节点中删除:
last_procstep = root.find('.//lineage/procstep[last()]')
last_procstep.getparent().remove(last_procstep)
  1. 使用 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 文档中带有相同标签的最后一个兄弟节点。