我有一个像这样的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
答案 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知识不够好,不能确定这个。我只知道它对我有用。