Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何使用xml.etree.elementtree正确删除子xml标记?_Python_Python 3.x_Xml_Elementtree - Fatal编程技术网

Python 如何使用xml.etree.elementtree正确删除子xml标记?

Python 如何使用xml.etree.elementtree正确删除子xml标记?,python,python-3.x,xml,elementtree,Python,Python 3.x,Xml,Elementtree,我试图从xml文件中删除所有子标记,同时保持父标记不变。我已经尝试通过循环元素来创建一个列表,并以这种方式删除它们,但是elementtree模块不喜欢这样 import xml.etree.ElementTree as ET tree = ET.parse("myfile") root = tree.getroot() for parent in root.find('parent'): child = parent.findall('child') #print(

我试图从xml文件中删除所有子标记,同时保持父标记不变。我已经尝试通过循环元素来创建一个列表,并以这种方式删除它们,但是elementtree模块不喜欢这样

import xml.etree.ElementTree as ET    

tree = ET.parse("myfile")
root = tree.getroot()

for parent in root.find('parent'):
    child = parent.findall('child')
    #print(len(child))
    root.remove(child)

tree.write("myfile")
我将print函数散列出来,以显示我可以在那里看到列表的正确长度

remove调用返回一个错误

TypeError: remove() argument must be xml.etree.ElementTree.Element, not list

我哪里做错了?我是否过分简化了ElementTree删除的工作方式?

findall
返回一个数组,因此您的
子项也就是一个数组。如果要删除所有子项,则必须为
child
as创建另一个循环

for parent in root.findall('parent'):
    children = parent.findall('child')
    for child in children:
        root.remove(child)
根据

findall()只查找带有直接标记的元素 当前元素的子元素。find()查找第一个子元素 带有特定标签

因此,如果您只有一个孩子,您可以使用
find
而不是
findall
。 因此,以下截取的内容将是有效的

for parent in root.find('parent'):
    child = parent.find('child')
    parent.remove(child)
更新一个完整的工作示例,其中包含写入文件的内容

import xml.etree.ElementTree as ET    

tree = ET.parse("test.xml")
root = tree.getroot()

for parent in root.findall('parent'):
    children = parent.findall('child')
    for child in children:
        parent.remove(child)
tree.write("test1.xml")
这个片段会变成

<foo>
    <parent>
        <child>
            <grandchild>
            </grandchild>
        </child>
        <child>
            <grandchild>
            </grandchild>
        </child>
        <child>
            <grandchild>
            </grandchild>
        </child>
    </parent>
    ...
</foo>

...
进入


...

谢谢。循环似乎可以正常工作,因为它将无错误运行,并且xml文件指示在进行更改时需要重新加载它。但是,在重新加载时,实际上没有发生任何更改。您知道python如何处理文件更改吗?我们是否将更改存储在内存中,并在重写之前将其丢失?我添加了一个完全工作的代码示例,可以满足您的需要,并在答案中更新了代码示例。为了回答您的问题,xml模块将整个文件加载到树变量中(如果xml无效,则引发异常)。文件中的
remove()
方法可能无法找到要删除的正确元素,因此文件中的最终输出不会更改。
write
方法仍然更新了文件,即使内容相同,因此尽管没有得到所需的结果,仍然会通知您该文件已更改。如果我在父级和子级上使用findall(),则会得到
ValueError:list.remove(x):x not in list
。我在循环中添加了类似这样的内容
,虽然True:try:root.remove(child)except:break
删除了该错误,但文件仍然没有更新。我认为我不必在root.find(“./root/祖父母/祖父母/父母”)中为父项显式设置位置,例如
。是这样吗?
<foo>
    <parent>
        </parent>
    ...
</foo>