python xml.etree - 删除节点但保留子节点(将子节点分配给祖父母)

时间:2016-06-24 20:05:40

标签: python xml xml-parsing

在Python中,如何删除节点但使用xml.etree API保留其子节点?

是的我知道那里有answer using lxml,但由于xml.etree是Python网站的一部分,我认为它也值得回答。

原始xml文件:

<?xml version="1.0"?>
<data>
    <country name="Liechtenstein">
        <rank>1</rank>
        <year>2008</year>
        <gdppc>141100</gdppc>
        <neighbor name="Austria" direction="E"/>
        <neighbor name="Switzerland" direction="W"/>
    </country>
    <country name="Singapore">
        <rank>4</rank>
        <year>2011</year>
        <gdppc>59900</gdppc>
        <neighbor name="Malaysia" direction="N"/>
    </country>
    <country name="Panama">
        <rank>68</rank>
        <year>2011</year>
        <gdppc>13600</gdppc>
        <neighbor name="Costa Rica" direction="W"/>
        <neighbor name="Colombia" direction="E"/>
    </country>
</data>

我想说我要移除country个节点但保留子节点并将它们分配给country的父节点?

理想情况下,我想要一个能够解决问题的解决方案&#34;到位&#34;而不是创建一个新树。

我的(非工作)解决方案:

# Get all parents of `country`
for country_parent in root.findall(".//country/.."):
    print(country_parent.tag)
    # Some countries could have same parent so get all
    # `country` nodes of current parent
    for country in country_parent.findall("./country"):
        print('\t', country.tag)
        # For each child of `country`, assign it to parent
        # and then delete it from `parent`
        for country_child in country:
            print('\t\t', country_child.tag)
            country_parent.append(country_child)
            country.remove(country_child)
        country_parent.remove(country)
tree.write("test_mod.xml")

输出打印语句:

data
     country
         rank
         gdppc
         neighbor
     country
         rank
         gdppc
     country
         rank
         gdppc
         neighbor

我们可以立即看到问题:country缺少标记year和一些neighbor标记。

结果.xml输出:

<data>
    <rank>1</rank>
        <gdppc>141100</gdppc>
        <neighbor direction="W" name="Switzerland" />
    <rank>4</rank>
        <gdppc>59900</gdppc>
        <rank>68</rank>
        <gdppc>13600</gdppc>
        <neighbor direction="E" name="Colombia" />
    </data>

这显然是错误的。

问题:为什么会这样?

我可以想象,通过附加/删除会破坏列表中的某些内容,即我已经无效&#34;列表类似于迭代器。

1 个答案:

答案 0 :(得分:1)

从您的程序中删除此行:

        country.remove(country_child)

xml.etree.ElementTree.Element的迭代基本上传递给list个子元素。在迭代期间修改该列表将产生奇怪的结果。