2010-01-31 16 views
43

Ich verwende das integrierte Python ElementTree-Modul. Es ist einfach, auf Kinder zuzugreifen, aber was ist mit Eltern- oder Geschwisterknoten? - Kann dies effizient durchgeführt werden, ohne den gesamten Baum zu durchlaufen?Zugriff elementTree Knoten Elternknoten

+1

Siehe http://stackoverflow.com/questions/374245/how-to-retrieve-the-parent-node-using- celementtree – kennytm

Antwort

33

Es gibt keine direkte Unterstützung in Form eines parent Attributs, aber Sie können vielleicht die beschriebenen Muster here verwenden, um den gewünschten Effekt zu erzielen. Der folgende Einzeiler wird vorgeschlagen (von der verlinkten zu schreiben), ein Kind zu Eltern-Mapping für einen ganzen Baum zu erstellen:

parent_map = dict((c, p) for p in tree.getiterator() for c in p) 
+0

Syntax Update, 2017/python3 'parent_map = {(c, p) für p in Baum.iter() für c in p} ' – gerardw

+1

Korrektur: ' parent_map = {c: p für p in root.iter() für c in p} ' – gerardw

14

Vinay's answer sollte immer noch funktionieren, aber für Python 2.7+ und 3.2+ der werden folgende Maßnahmen empfohlen:

parent_map = {c:p for p in tree.iter() for c in p} 

getiterator() für iter() ist veraltet, und es ist schön, das neue dict Liste Verständnis Konstruktor zu verwenden.

Zweitens, beim Erstellen eines XML-Dokuments ist es möglich, dass ein Kind mehrere Eltern hat, obwohl dies entfernt wird, sobald Sie das Dokument serialisieren. Wenn es ankommt, können Sie versuchen, diese:

parent_map = {} 
for p in tree.iter(): 
    for c in p: 
     if c in parent_map: 
      parent_map[c].append(p) 
      # Or raise, if you don't want to allow this. 
     else: 
      parent_map[c] = [p] 
      # Or parent_map[c] = p if you don't want to allow this 
+1

Was passiert, wenn Sie keinen Zugriff auf den Baum haben? Wie nach einer .find() – Brett

+1

Ich kenne keine Möglichkeit, den Wurzelknoten (und damit Eltern/Vorfahren) zu erhalten, wenn Sie nicht einen Verweis darauf gespeichert haben. Aber ich verstehe nicht, wie '.find()' damit zu tun hat. – supergra

+0

Ich habe '' find() 'als Beispielfunktion verwendet, die einfach ein Element zurückgibt – Brett

2

Eine andere Möglichkeit, wenn nur ein einzelnes Subelement der Eltern wollen und auch die Subelement XPath bekannt.

parentElement = subElement.find(xpath+"/..") 
+2

Funktioniert nicht für mich, ich bekomme 'None' - gleich, wenn ich nur' subElement.find ('..') 'benutze. – damian

1

Wenn Sie lxml verwenden, konnte ich das übergeordnete Element mit dem folgenden erhalten:

parent_node = next(child_node.iterancestors()) 

Dies wird zu erhöhen, um eine StopIteration Ausnahme, wenn das Element Vorfahren nicht haben - so vorbereitet werden, um das zu fangen, wenn Sie in dieses Szenario kommen.

4

Sie können die Schreibweise xpath ... in ElementTree verwenden.

<parent> 
    <child id="123">data1</child> 
</parent> 

xml.findall('.//child[@id="123"]...') 
>> [<Element 'parent'>] 
+0

Dies ist eine fantastische Lösung, arbeitet mit find() auch wenn Sie wissen, dass es nur ein einzelnes Element, das Sie suchen, gibt. Wie folgt: 'root.find (" .//*[@testname = 'generated_sql'] ... ")' – Bostone

3

Wie in Get parent element after using find method (xml.etree.ElementTree) erwähnt würden Sie eine indirekte Suche nach Eltern zu tun haben. Mit xml:

<a> 
<b> 
    <c>data</c> 
    <d>data</d>  
</b> 
</a> 

Angenommen, Sie etree Element in xml Variable erstellt haben, können Sie verwenden:

In[1] parent = xml.find('.//c/..') 
In[2] child = parent.find('./c') 

in Resultierende:

Out[1]: <Element 'b' at 0x00XXXXXX> 
Out[2]: <Element 'c' at 0x00XXXXXX> 

Höhere Eltern würden als zu finden: secondparent=xml.find('.//c/../..') Sein <Element 'a' at 0x00XXXXXX>

1

Schauen Sie sich die 19.7.2.2 an. Sektion: Supported XPath syntax ...

Suche Knoten der Eltern mit dem Pfad:

parent_node = node.find('..') 
+1

Hast du das getestet? Wenn Sie es schaffen konnten, senden Sie bitte ein vollständiges Codebeispiel, das es demonstriert. Siehe diesen Kommentar: https://stackoverflow.com/questions/2170610/access-elementtree-node-parent-node#comment44519212_21963494 – mzjn

+1

Die Python 3-Dokumentation sagt: "Gibt' None' zurück, wenn der Pfad versucht, die Vorfahren des Starts zu erreichen Element (das Element 'find' wurde aufgerufen)." (https://docs.python.org/3/library/xml.etree.elementtree.html#supported-xpath-syntax). – mzjn

+0

Funktioniert für mich. Die beste und beste Antwort. – ToTenMilan

Verwandte Themen