2017-02-23 34 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知識不夠好,無法確定這個壽命。我只知道這對我來說很有用。