pythonxml etree按子节点的文本查找父节点

2024-10-01 07:41:21 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个这样的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>。在

用下面的话我可以知道这个名字

^{pr2}$

但是我不能使用名称.查找('..)它告诉我

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

是否有可能访问<user><user>子级,其中name中的文本是“user1”?在

预期结果:

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

重要注意:我不能使用lxml来使用getparent()方法,我只能xml.etree


Tags: name名称accessgroupxml名字listattributeerror
3条回答

如果有人对用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))

在这之后等倾翻(tree)显示树现在包含正确更改的用户子树,并添加了另一个group标记。在

注意:我不太确定为什么这样做,我只希望yield提供对树的引用,因此更改返回的父级yield会改变原始树。我的python知识还不足以确定这一点。我只知道这样对我有效。在

您可以编写递归方法来遍历树并捕获父级。在

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>]

如果您使用的是python3.X,那么可以使用漂亮的yield from ...语法,而不是迭代递归调用。在

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

To do that, using 'find', you need to do like this: for ele in name: ele.find('..') # To access ele as an element

相关问题 更多 >