Domanda

Sto usando il modulo Python ElementTree incorporato. E 'semplice da bambini accesso, ma per quanto riguarda i nodi genitore o un fratello? -? Questo può essere fatto in modo efficiente senza attraversare l'intero albero

È stato utile?

Soluzione

Non c'è alcun supporto diretto sotto forma di un attributo parent, ma si può forse utilizzare gli schemi descritti qui per ottenere l'effetto desiderato. Di seguito uno-liner si suggerisce (dal legata al post) per creare una mappatura bambino-to-genitore per un intero albero:

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

Altri suggerimenti

dovrebbe funzionare, ma per Python 2.7+ e 3.2 + Si raccomanda di Vinay risposta quanto segue:

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

getiterator() è deprecato in favore di iter(), ed è bello per utilizzare il nuovo costruttore lista dict comprensione.

In secondo luogo, mentre la costruzione di un documento XML, è possibile che un bambino avrà più i genitori, anche se questo viene rimosso una volta che si serializzare il documento. Se quello che conta, si potrebbe provare questo:

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

È possibile utilizzare la notazione XPath ... in ElementTree.

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

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

Come accennato in Get elemento principale dopo aver usato find metodo (xml.etree.ElementTree) che avrebbe dovuto fare una ricerca indiretta per il genitore. Avendo xml:

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

Supponendo che avete creato elemento eTree nella variabile xml, è possibile utilizzare:

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

Con conseguente:

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

genitore superiore sarebbe trovato come: secondparent=xml.find('.//c/../..') essere <Element 'a' at 0x00XXXXXX>

Il XPath '..' selettore non può essere utilizzato per recuperare il nodo padre sulla 3.5.3 3.6.1 né (almeno su OSX), ad esempio, in modalità interattiva:

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

l'ultima risposta rompe tutte le speranze ...

Un altro modo se vogliono solo genitore di un singolo elemento secondario e anche conosciuta XPath del sottoelemento.

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

Se si utilizza lxml, sono stato in grado di ottenere l'elemento padre con la seguente:

parent_node = next(child_node.iterancestors())

Questo solleva un'eccezione StopIteration se l'elemento non ha antenati - in modo da essere pronti a cogliere che, se si può incorrere in questo scenario

.

incollare qui la mia risposta da https://stackoverflow.com/a/54943960/492336 :

Ho avuto un problema simile e ho avuto un po 'creativo. Si scopre che niente ci impedisce di aggiungere informazioni parentela noi stessi. dopo possiamo spogliare una volta non abbiamo più bisogno di esso.

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())

Guardate la 19.7.2.2. Sezione: supportati XPath sintassi ...

Trova genitore del nodo utilizzando il percorso:

parent_node = node.find('..')
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top