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

Python xml etree通过子节点的文本查找父节点,python,xml,Python,Xml,我有一个这样的XML <xml> <access> <user> <name>user1</name> <group>testgroup</group> </user> <user> <name>user2</name>

我有一个这样的XML

<xml>
    <access>
        <user>
            <name>user1</name>
            <group>testgroup</group>
        </user>
        <user>
            <name>user2</name>
            <group>testgroup</group>
        </user>
    <access>
</xml>
但我无法使用name.find(“…”)访问父级,它告诉我

AttributeError: 'list' object has no attribute 'find'.
是否有可能访问名为“user1”的
的确切
子级

预期结果:

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

用户1
测试组
测试组2
用户2
测试组
重要提示:我不能使用lxml来使用getparent()方法,我只能使用xml.etree

要做到这一点,使用“查找”,您需要这样做:对于名称中的元素: ele.find(“..”)#将ele作为元素访问


如果有人对用xml而不是lxml来做这件事感兴趣的话,下面是我如何解决这个问题的

根据

将xml.etree.ElementTree作为et导入
tree=et.parse(my_xmlfile)
root=tree.getroot()
access=root.find('access')
# ... 剪
def iterparent(树):
对于树中的父级。getiterator():
对于父对象中的子对象:
让出父母、孩子
#users=需要添加新组的用户名列表
#通过tupel进行iter并找到用户名
#找到时更改xml树
对于用户中的用户:
打印“正在处理用户:%s”%user
对于iterparent中的父级、子级(访问):
如果child.tag==“name”和child.text==用户:
打印“找到的名称:%s”%user
parent.append(et.fromstring(“%s”%new\u组))
在此之后,et.dump(tree)显示树现在包含正确修改的用户子树,并添加了另一个组标记


注意:我不太清楚为什么会这样,我只是希望收益率提供对树的引用,因此改变返回的父收益率会改变原始树。我的python知识还不足以确定这个tho。我只知道它对我来说是这样的。

您可以编写一个递归方法来遍历树并捕获父树

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>]
def递归树(节点):
对于节点中的子节点。getchildren():
如果child.text==“user1”:
屈服点
对于递归树(子)中的子子子级:
产量子代
打印列表(递归树(根))
# []
如果您使用的是Python3.X,那么可以使用漂亮的
yield from…
语法,而不是迭代递归调用


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

您已将
名称设置为列表,因此当然没有
查找
属性,因为列表对象没有该方法。我知道。很明显,这就是错误消息告诉我的。但是我该如何解决我的问题呢?向我们展示您预期的XML结果。我不知道,但我认为我已经编写了我想要添加的内容。尽管如此,我还是用我的预期结果更新了问题。我不想访问ele。我需要ele.getParent(),但它在xml中不存在。etree:是parent,我想查找并附加到另一个条目。在这种情况下,“node”将保留父项,以便我可以使用node.append(et.fromstring)访问它(…if语句中的ect ect,对吗?我已经读过关于yield的内容,但还不完全了解它在内部是如何工作的…@dreamyrhodes是的,
node
将容纳父元素。解释yield超出了注释的范围,但基本上它是在函数中构建父元素列表的一种替代方法。是的,当然会评论太多了。我只是觉得奇怪,这是可行的(以及下面我自己的解决方案),并且生成树的对象,然后修改它们会使原始xml树发生更改。无论如何,谢谢你的建议,因为你的建议比我的解决方案短。
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))
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>]