access ElementTree node parent node

2019-01-02 20:53发布

I am using the builtin Python ElementTree module. It is straightforward to access children, but what about parent or sibling nodes? - can this be done efficiently without traversing the entire tree?

8条回答
栀子花@的思念
2楼-- · 2019-01-02 21:21

Vinay's answer should still work, but for Python 2.7+ and 3.2+ the following is recommended:

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

getiterator() is deprecated in favor of iter(), and it's nice to use the new dict list comprehension constructor.

Secondly, while constructing an XML document, it is possible that a child will have multiple parents, although this gets removed once you serialize the document. If that matters, you might try this:

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
查看更多
冷夜・残月
3楼-- · 2019-01-02 21:24

Look at the 19.7.2.2. section: Supported XPath syntax ...

Find node's parent using the path:

parent_node = node.find('..')
查看更多
无与为乐者.
4楼-- · 2019-01-02 21:26

As mentioned in Get parent element after using find method (xml.etree.ElementTree) you would have to do an indirect search for parent. Having xml:

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

Assuming you have created etree element into xml variable, you can use:

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

Resulting in:

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

Higher parent would be found as:secondparent=xml.find('.//c/../..') being <Element 'a' at 0x00XXXXXX>

查看更多
美炸的是我
5楼-- · 2019-01-02 21:33

You can use xpath ... notation in ElementTree.

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

xml.findall('.//child[@id="123"]...')
>> [<Element 'parent'>]
查看更多
梦该遗忘
6楼-- · 2019-01-02 21:33

If you are using lxml, I was able to get the parent element with the following:

parent_node = next(child_node.iterancestors())

This will raise a StopIteration exception if the element doesn't have ancestors - so be prepared to catch that if you may run into that scenario.

查看更多
只靠听说
7楼-- · 2019-01-02 21:36

Another way if just want a single subElement's parent and also known the subElement's xpath.

parentElement = subElement.find(xpath+"/..")
查看更多
登录 后发表回答