从etree中移除节点但保留子节点

2 投票
3 回答
1203 浏览
提问于 2025-04-18 05:34

我正在遍历一个XML树,但在提取树中的一个节点时遇到了一些麻烦,想要保留它里面的子节点。

举个例子:

<xml>
    <letter name="B">
        <letter name="D">
            <letter name="E">
                <letter name="F">
                    <letter name="G">

                    </letter>
                </letter>
            </letter>
        </letter>
    </letter>
</xml>

我需要的结果是这样的:

<xml>
    <letter name="B">
        <letter name="D">
                <letter name="F">
                    <letter name="G">

                    </letter>
                </letter>
        </letter>
    </letter>
</xml>

但是我无法做到这一点,因为这样会把所有的E子节点都删掉。

谢谢!

3 个回答

0

我刚刚完成这个任务,我只需要在删除之前复制一份树结构,不然原来的对象会被修改。

这是解决方案。顺便说一下,非常感谢!!!!XD

def remove_letter(tree_original, letter):
    tree= copy.deepcopy(tree_original)
    for parent in tree.getiterator():
        for child in parent:
            if child.attrib.get('name') == letter:
                parent.remove(child)
                parent.extend(child)
                print etree.tostring(parent)
                return parent   

def get_next_trees(tree):
    my_trees = []
    for parent in tree.getiterator():
        if child.attrib.get('name') == "D":
            for child in parent:
                my_trees.append(remove_letter(tree)
            return my_trees 
0

还有一件事,

这样做可能吗??

最初的XML内容是

<xml>
    <letter name="B">
        <letter name="D">
            <letter name="E">
                <letter name="F">
                    <letter name="G">

                    </letter>
                </letter>
            </letter>
            <letter name="H">
                <letter name="I">

                </letter>
            </letter>
        </letter>
    </letter>
</xml>

然后希望输出是一个包含两个树的列表,像这样:

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

                </letter>
            </letter>
        </letter>
    </letter>
</xml>


<xml>
    <letter name="B">
            <letter name="H">
                <letter name="I">

                </letter>
            </letter>
    </letter>
</xml>

你们可以看到,@falsetru 和 @alecxe,我只是删除了D,只保留了每棵树的一个孩子。

谢谢!!!!

5

这个想法是找到一个名为 letter 的元素,它的名字是 "E",然后获取它的父元素,接着从父元素中移除这个元素,最后把这个元素的孩子们添加到父元素中:

import xml.etree.ElementTree as etree

data = """
<xml>
    <letter name="B">
        <letter name="D">
            <letter name="E">
                <letter name="F">
                    <letter name="G">

                    </letter>
                </letter>
            </letter>
        </letter>
    </letter>
</xml>
"""

XPATH = './/letter[@name="E"]'

tree = etree.fromstring(data)
letter = tree.find(XPATH)
parent = tree.find(XPATH + '/..')

parent.remove(letter)
parent.extend(letter)

print etree.tostring(tree)

它会打印出:

<xml>
    <letter name="B">
        <letter name="D">
            <letter name="F">
                    <letter name="G">

                    </letter>
                </letter>
            </letter>
    </letter>
</xml>

更新(使用迭代的方法):

def iterparent(tree):
    for parent in tree.getiterator():
        for child in parent:
            yield parent, child

tree = etree.fromstring(data)
for parent, child in iterparent(tree):
    if child.tag == "letter" and child.attrib.get('name') == "E":
        parent.remove(child)
        parent.extend(child)

print etree.tostring(tree)

iterparent() 函数是从文档中的 访问父元素 这一段中获取的。

撰写回答