2

我需要“get_ancestors_recursively”函数。
样品运行可以是

>>> dump(tr)
<anc1>
  <anc2>
    <element> </element>
  </anc2>
</anc1>
>>> input_element = tr.getiterator("element")[0]
>>> get_ancestors_recursively(input_element)
['anc1', 'anc2']

有人可以帮我吗?

4

3 回答 3

3

另一种选择是LXML,它为内置的 ElementTree api 提供有用的扩展。如果你愿意安装一个外部模块,它有一个很好的Element.getparent()功能,你可以简单地递归调用,直到到达ElementTree.getroot(). 这可能是最快和最优雅的解决方案(因为为lxml.etree module指向其父元素的元素引入了指针属性,而不是在整个树中搜索正确的parent/child对)。

于 2010-06-17T17:54:00.740 回答
2

在最新版本的 ElementTree(v1.3 或更高版本)中,您可以简单地做

input_element.find('..')

递归地。但是,Python 附带的 ElementTree 没有此功能,并且我在 Element 类中看不到任何向上的东西。

我相信这意味着您必须以艰难的方式做到这一点:通过对元素树的详尽搜索。

def get_ancestors_recursively(e, b):
    "Finds ancestors of b in the element tree e."
    return _get_ancestors_recursively(e.getroot(), b, [])

def _get_ancestors_recursively(s, b, acc):
    "Recursive variant. acc is the built-up list of ancestors so far."
    if s == b:
        return acc
    else:
        for child in s.getchildren():
            newacc = acc[:]
            newacc.append(s)
            res = _get_ancestors_recursively(child, b, newacc)
            if res is not None:
                return res
        return None

由于 DFS,这很慢,并且会生成很多垃圾收集列表,但如果你能处理它应该没问题。

于 2010-06-14T22:41:57.463 回答
0

从大量谷歌搜索中找到了这个小宝石(http://elmpowered.skawaii.net/?p=74

parent = root.findall(".//{0}/..".format(elem.tag))

root 这里是树的根节点。elem 是您从迭代中获得的实际元素对象。

这确实需要您知道根,这可能意味着更改您为 XML 解析设置的方式,但它充其量只是次要的。

于 2015-06-15T18:53:07.230 回答