0

我试图删除给定元素的所有兄弟姐妹:

例如,给定这个 etree 对象

<xml>
    <letter name="A">
            <letter name="B">
                    <letter name="C">
                    </letter>
                    <letter name="D">
                    </letter>
                    <letter name="G">
                    </letter>
                    <letter name="H">
                    </letter>
                    <letter name="I">
                    </letter>
            </letter>
            <letter name="E">
                <letter name="F">
                </letter>
            </letter>
    </letter>
</xml>

我想删除所有 G 节点兄弟并返回:

<xml>
    <letter name="A">
            <letter name="B">
                    <letter name="G">
                    </letter>
            </letter>
            <letter name="E">
                <letter name="F">
                </letter>
            </letter>
    </letter>
</xml>

不使用 xpath 或 find,以迭代方式。

你能提供一些关于如何做到这一点的提示吗?

这是我刚刚写的代码

import xml.etree.ElementTree as etree
data = """

<xml>
    <letter name="A">
            <letter name="B">
                    <letter name="C">
                    </letter>
                    <letter name="D">
                    </letter>
                    <letter name="G">
                    </letter>
                    <letter name="H">
                    </letter>
                    <letter name="I">
                    </letter>
            </letter>
            <letter name="E">
                <letter name="F">
                </letter>
            </letter>
    </letter>
</xml>

"""
tree =etree.fromstring(data)


for parent in tree.getiterator():
    for child in parent:
        for subchild in child:
            if subchild.attrib.get('name') == "G":
                parent_name = child.attrib.get('name')
                #print parent_name

for parent in tree.getiterator():
    if parent.attrib.get('name') == parent_name:
        for child in parent:
            if child.attrib.get('name') == "G":
                print "not this"
            else:
                parent.remove(child)


print etree.tostring(tree)

干杯!

4

1 回答 1

1

你很亲密。G一旦找到 name ,您将需要通过包含 name 的任何元素来重申G。因此,您将希望在这些方面使用更多的东西(根据您的要求,它使用迭代而不是 xpath 或查找):

>>> def remove(name, value, root):
    """
    Iterates through the @root element and removes elements
    where the @name != @value.
    """
    for element in root:
        if element.attrib.get(name) != value:
            root.remove(element)


>>> def remove_siblings_of(name, value, root):
    """
    Recursively removes from the @root element all elements which (1) do
    not have @name == @value but (2) do have a sibling where @name == @value.
    """
    for element in root:
        if element.attrib.get(name) == value:
            remove(name, value, root)  # need to reiterate through element now to remove previous siblings
        if len(element):
            remove_siblings_of(name, value, element)
    return root

当您在 xml 上使用后一个函数时,您将获得所需的结果:

>>> siblings_removed = remove_siblings_of('name', 'G', root)
>>> print et.tostring(siblings_removed)
<xml>
    <letter name="A">
            <letter name="B">
                    <letter name="G">
                    </letter>
                    </letter>
            <letter name="E">
                <letter name="F">
                </letter>
            </letter>
    </letter>
</xml>
于 2014-05-21T12:44:09.633 回答