2017-02-23 33 views
0

的文本查找父节点我有一个XML认为是这样的Python中的XML etree由孩子

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

我现在想要一个<group>testgroup2</group>添加到USER1子树。

使用下面的我能得到的名称

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

但我不能访问使用父name.find(“..”),它告诉我

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

有什么可能访问的确切<user>孩子的<access>凡在名字旁边的文字是“用户1”?

预期结果:

<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

+0

你设置'name'到一个列表,所以当然没有'find'属性,如列表对象没有这样的方法。 – eijen

+0

我知道。这就是错误信息明显告诉我的。但是我怎样才能解决我的问题? – user6329530

+0

向我们展示您的预期XML结果。 – swatchai

回答

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 ...语法,而不是遍历的递归调用。

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

+0

在这种情况下,“节点”将保存父节点,以便我可以通过node.append访问它(et.fromstring(在if语句中...等等,对吗?我已经阅读了关于yield的知识,但尚未完全理解它是如何在内部工作的...... – user6329530

+0

@dreamyrhodes是的,'node'将包含parent,解释yield超出了注释的范围,但基本上它是构造函数中父元素列表的一种替代方法 –

+0

Yes当然这对评论太多了,我只是感到困惑,它的工作原理(以及我自己的解决方案),并产生树的对象,然后改变它们,使原来的XML树改变。谢谢无论如何,因为你的建议是比我的解决方案更短。 – user6329530

0

要做到这一点,使用'发现 '你需要做的是这样的:对于ELE在名称: ele.find(' ..')#进入ELE作为一个元素

+0

我不想访问ele。我需要ele.getParent(),但在xml中不存在。etree:是父母,我想查找并附加到另一个条目。 – user6329530

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(树)后,根据建议表明,树现在包含正确改变用户子树另一组标签添加。

注:我真的不知道为什么这个作品,我只是期望收益率给树的引用,并因此改变母产量返回改变了原来的树。我的Python知识不够好,无法确定这个寿命。我只知道这对我来说很有用。