访问ElementTree节点父节点

时间:2010-01-31 05:02:48

标签: python elementtree

我正在使用内置的Python ElementTree模块。访问子节点很简单,但父节点或兄弟节点呢? - 这可以在不遍历整棵树的情况下有效地完成吗?

10 个答案:

答案 0 :(得分:42)

parent属性没有直接支持,但您可以使用here描述的模式来达到预期的效果。建议使用以下单行(从链接到帖子)为整棵树创建子到父映射:

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

答案 1 :(得分:19)

Vinay's answer应该仍然可以使用,但对于Python 2.7+和3.2+,建议使用以下内容:

parent_map = {c:p for p in tree.iter() for c in p}
不推荐使用

getiterator()以支持iter(),并且使用新的dict列表推导构造函数很好。

其次,在构建XML文档时,子项可能有多个父项,尽管在序列化文档后会删除它。如果这很重要,你可以试试这个:

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

答案 2 :(得分:9)

您可以在ElementTree中使用xpath ...表示法。

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

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

答案 3 :(得分:5)

Get parent element after using find method (xml.etree.ElementTree)中所述,您必须间接搜索父级。 有xml:

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

假设您已在xml变量中创建了etree元素,您可以使用:

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

导致:

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

更高级的父级将被视为:secondparent=xml.find('.//c/../..')<Element 'a' at 0x00XXXXXX>

答案 4 :(得分:3)

XPath'..'选择器不能用于在3.5.3或3.6.1(至少在OSX上)上检索父节点, 例如在交互模式下:

const result = [];

for(const {type, details, id} of input)
  for(const number of details.split("."))
     result.push({ number, type, id });

最后一个答案打破了所有希望...

答案 5 :(得分:2)

另一种方法,如果只想要一个子元素的父元素,也知道subElement的xpath。

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

答案 6 :(得分:1)

如果您使用的是lxml,我可以使用以下内容获取父元素:

parent_node = next(child_node.iterancestors())

如果元素没有祖先,这将引发StopIteration异常 - 所以如果你遇到那种情况,请准备抓住它。

答案 7 :(得分:1)

在这里粘贴https://stackoverflow.com/a/54943960/492336的答案:

我有一个类似的问题,我有点创意。事实证明,没有什么阻止我们自己添加育儿信息。以后我们不再需要它时就可以剥离它。

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

答案 8 :(得分:1)

得到答复

https://towardsdatascience.com/processing-xml-in-python-elementtree-c8992941efd2

提示:在 XPath 中使用 '...' 返回当前元素的父元素。


for object_book in root.findall('.//*[@name="The Hunger Games"]...'):
    print(object_book)

答案 9 :(得分:-1)

看看19.7.2.2。部分:Supported XPath syntax ...

使用路径查找节点的父级:

parent_node = node.find('..')