ElementTree 删除元素

问题描述 投票:0回答:2

这里是Python菜鸟。想知道 remove 所有

profile
属性值为
updated
的“
true
”标签的最干净、最好的方法是什么。

我尝试了以下代码,但它抛出:SyntaxError(“不能在元素上使用绝对路径”)

 root.remove(root.findall("//Profile[@updated='true']"))

XML:

<parent>
  <child type="First">
    <profile updated="true">
       <other> </other>
    </profile>
  </child>
  <child type="Second">
    <profile updated="true">
       <other> </other>
    </profile>
  </child>
  <child type="Third">
     <profile>
       <other> </other>
    </profile>
  </child>
</parent>
python xml python-2.7 scripting elementtree
2个回答
8
投票

如果您使用

xml.etree.ElementTree
,您应该使用
remove()
方法来删除节点,但这需要您有父节点引用。因此,解决方案:

import xml.etree.ElementTree as ET

data = """
<parent>
  <child type="First">
    <profile updated="true">
       <other> </other>
    </profile>
  </child>
  <child type="Second">
    <profile updated="true">
       <other> </other>
    </profile>
  </child>
  <child type="Third">
     <profile>
       <other> </other>
    </profile>
  </child>
</parent>"""

root = ET.fromstring(data)
for child in root.findall("child"):
    for profile in child.findall(".//profile[@updated='true']"):
        child.remove(profile)

print(ET.tostring(root))

打印:

<parent>
  <child type="First">
    </child>
  <child type="Second">
    </child>
  <child type="Third">
     <profile>
       <other> </other>
    </profile>
  </child>
</parent>

请注意,使用

lxml.etree
这会更简单一些:

root = ET.fromstring(data)
for profile in root.xpath(".//child/profile[@updated='true']"):
    profile.getparent().remove(profile)

其中

ET
是:

import lxml.etree as ET

0
投票

我寻找一种使用内置

xml
库直接寻址要删除的元素的方法。解决办法如下:

import itertools
from xml.etree import ElementTree

def removeall(root: ElementTree.Element, match, namespaces=None):
    parent_by_child=dict(itertools.chain.from_iterable(
        ((child, element) for child in element) for element in root.iter()))

    for element in root.findall(match, namespaces):
        parent_by_child[element].remove(element)

应用于您的数据:

data = """
<parent>
  <child type="First">
    <profile updated="true">
       <other> </other>
    </profile>
  </child>
  <child type="Second">
    <profile updated="true">
       <other> </other>
    </profile>
  </child>
  <child type="Third">
     <profile>
       <other> </other>
    </profile>
  </child>
</parent>"""

root = ElementTree.fromstring(data)
removeall(root, "./child/profile[@updated='true']")
print(ElementTree.tostring(root, encoding='unicode'))

打印:

<parent>
  <child type="First">
    </child>
  <child type="Second">
    </child>
  <child type="Third">
     <profile>
       <other> </other>
    </profile>
  </child>
</parent>

由于问题标有python2.7:我需要承认,我不知道我用来构建child-parent-dict的

itertools.chain.from_iterable
是否已经存在于python2.7中。

© www.soinside.com 2019 - 2024. All rights reserved.