xml.etree.ElementTree插入到创建无限循环Python的子节点的子节点中

时间:2018-09-19 17:55:46

标签: xml python-3.x elementtree

我正在尝试在大型XML文档(约2000行)的子节点的特定子节点处插入元素,这是我的代码:

import xml.etree.cElementTree as ET
class Kapow_commands:
    tree = ET.parse('location/of/xml/file')
    root = tree.getroot()
    seq_id = 39

    def __init__(self):
        pass

    def append(self, block):
        node_num=0 
        for node in Kapow_commands.root[13][1]:
            node_num=node_num+1
            if node.get('class') == 'End':
                node.attrib['id'] = str(Kapow_commands.seq_id + 1)
                print(node.attrib)
                print(node_num)
                Kapow_commands.root[13][1].insert(node_num -1, block)


block = ET.Element("test")    

Kapow_commands().append(block)

此代码在特定节点上扫描XML文件以查找class ='End',然后在该元素id上加1并在其前面插入另一个元素。但是,当我运行此命令时,似乎会创建一个无限循环,因为它不会停止在此位置插入元素。有谁知道为什么会这样?或关于如何在所需位置正确插入此元素的任何想法?

2 个答案:

答案 0 :(得分:0)

我有一个类似的问题。

解决方案是将要添加的元素初始化到循环中。

因此,在您的情况下,我将传递一个名称作为参数,并使代码如下所示:

def append(self, blockName): # here comes the name
    node_num=0 
    for node in Kapow_commands.root[13][1]:
        block = ET.Element(name) # and there goes the init
        node_num=node_num+1
        if node.get('class') == 'End':
            node.attrib['id'] = str(Kapow_commands.seq_id + 1)
            print(node.attrib)
            print(node_num)
            Kapow_commands.root[13][1].insert(node_num -1, block)

对于我来说,它成功了。不幸的是,我不知道这种魔术背后的原因。

答案 1 :(得分:0)

修复

如您的注释中所述,在插入新元素之后插入break语句可解决无限循环的问题。

代码为什么会产生无限循环

至于为什么我们得到一个无限循环,我们需要了解当我们在python中调用for循环时会发生什么。从docs中我们看到一个for循环在您的可迭代对象(在本例中为Kapow_commands.root[13][1])上创建了一个迭代器,该迭代器在我们中断它,序列为空或迭代器引发时终止StopIteration异常。实际上,如果我们扩展for node in Kapow_commands.root[13][1]:,我们将得到类似

的东西
iterator = iter(Kapow_commands.root[13][1])
while True:
    try:
        node  = iterator.__next__()
        # Body of for loop
    except StopIteration:
        break

神奇的地方就在这里。让我们用“ End” End Node类来调用该节点。如果当前节点为End Node,则执行Kapow_commands.root[13][1].insert(node_num -1, block)。这会将block插入到可迭代对象的当前位置中,这意味着可迭代对象中的下一项再次变为End Node。在for循环的下一次迭代中,iterator.__next__()给我们End Node,我们回到了开始的地方,产生了无限循环。