Python xml etree通过child的文本查找父节点

时间:2017-02-23 17:04:59

标签: python xml

我有一个像这样的XML

<xml>
    <access>
        <user>
            <name>user1</name>
            <group>testgroup</group>
        </user>
        <user>
            <name>user2</name>
            <group>testgroup</group>
        </user>
    <access>
</xml>

我现在想在user1子树中添加<group>testgroup2</group>

使用以下内容我可以获得名称

access = root.find('access')
name = [element for element in access.iter() if element.text == 'user1']

但我无法使用name.find('..')访问父级,它告诉我

AttributeError: 'list' object has no attribute 'find'.

是否有可能访问名称中的文字为“user1”的<user>的{​​{1}}个孩子?

预期结果:

<access>

重要提示:我不能使用lxml来使用getparent()方法,我坚持使用xml.etree

3 个答案:

答案 0 :(得分:1)

您可以编写一个递归方法来迭代树并捕获父项。

def recurse_tree(node):
    for child in node.getchildren():
        if child.text == 'user1':
            yield node
        for subchild in recurse_tree(child):
            yield subchild

print list(recurse_tree(root)) 
# [<Element 'user' at 0x18a1470>]

如果您使用的是Python 3.X,则可以使用漂亮的yield from ...语法,而不是遍历递归调用。

请注意,这可能会多次生成相同的节点(如果有多个子节点包含目标文本)。您可以使用一个集来删除重复项,也可以更改控制流以防止这种情况发生。

答案 1 :(得分:0)

  

要做到这一点,使用'find',你需要这样做:for ele in name:       ele.find('..')#将ele作为元素访问

答案 2 :(得分:0)

以下是我如何解决这个问题,如果有人有兴趣在xml而不是lxml中做这些事情(为什么呢)。

根据

的建议

http://effbot.org/zone/element.htm#accessing-parents

import xml.etree.ElementTree as et

tree = et.parse(my_xmlfile)
root = tree.getroot()
access = root.find('access')

# ... snip ...

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

# users = list of user-names that need new_group added
# iter through tupel and find the username
# alter xml tree when found

for user in users:
    print "processing user: %s" % user
    for parent, child in iterparent(access):
        if child.tag == "name" and child.text == user:
            print "Name found: %s" % user
            parent.append(et.fromstring('<group>%s</group>' % new_group))

此后et.dump(树)显示树现在包含正确更改的用户子树,并添加了另一个组标记。

注意:我不确定为什么会这样,我只是期望yield给出对树的引用,因此更改返回的父yield会改变原始树。我的python知识不够好,不能确定这个。我只知道它对我有用。