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