Frage

Ich bin mit dem eingebauten Python ElementTree Modul. Es ist für den Zugriff Kinder einfach, aber was Eltern oder Geschwister-Knoten? - kann dies effizient durchgeführt werden, ohne den gesamten Baum durchlaufen

War es hilfreich?

Lösung

Es gibt keine direkte Unterstützung in Form eines parent Attribut, aber man kann vielleicht die Muster verwenden beschrieben

Andere Tipps

Vinay Antwort sollte noch Arbeit, aber für Python 2.7+ und 3.2+ folgende empfohlen:

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

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

Zweitens, während ein XML-Dokument Konstruktion ist es möglich, dass ein Kind mehrere Eltern haben wird, obwohl diese entfernt wird, sobald Sie das Dokument serialisiert. Wenn diese Fragen, 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

Sie können XPath ... Notation in ElementTree verwenden.

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

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

Wie bereits erwähnt in Get Eltern-Elemente nach FIND Methode (xml.etree.ElementTree) Sie eine indirekte Suche nach Eltern zu tun haben würde. Mit xml:

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

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

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

Resultat:

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

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

Der XPath ‚..‘ Wähler können nicht den übergeordneten Knoten auf 3.5.3 noch 3.6.1 abzurufen verwendet werden (zumindest auf OSX), zB im interaktiven Modus:

import xml.etree.ElementTree as ET
root = ET.fromstring('<parent><child></child></parent>')
child = root.find('child')
parent = child.find('..') # retrieve the parent
parent is None # unexpected answer True

Die letzte Antwort bricht alle Hoffnungen ...

Eine andere Möglichkeit, wenn Sie möchten, nur einen einzigen Teilelement der Eltern und auch die Subelement XPath bekannt.

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

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

parent_node = next(child_node.iterancestors())

Dies wird eine StopIteration Ausnahme auslösen, wenn das Element Vorfahren nicht haben - so zu fangen vorbereitet sein, dass, wenn Sie in diesem Szenario ausführen kann

.

Einfügen hier meine Antwort von https://stackoverflow.com/a/54943960/492336 :

Ich hatte ein ähnliches Problem, und ich habe ein bisschen kreativ. Stellt sich heraus, nichts hindert uns daran, Hinzufügen der Abstammungs info uns. Wir können es später abzustreifen, sobald wir nicht mehr benötigen.

def addParentInfo(et):
    for child in et:
        child.attrib['__my_parent__'] = et
        addParentInfo(child)

def stripParentInfo(et):
    for child in et:
        child.attrib.pop('__my_parent__', 'None')
        stripParentInfo(child)

def getParent(et):
    if '__my_parent__' in et.attrib:
        return et.attrib['__my_parent__']
    else:
        return None

# Example usage

tree = ...
addParentInfo(tree.getroot())
el = tree.findall(...)[0]
parent = getParent(el)
while parent:
    doSomethingWith(parent)
    parent = getParent(parent)
stripParentInfo(tree.getroot())

Sehen Sie sich die 19.7.2.2. Abschnitt: Unterstützte XPath-Syntax ...

Finden Knoten der Eltern mit dem Pfad:

parent_node = node.find('..')
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top