在Python ElementTree中,如何获取树中元素的所有祖先的列表?

发布于 2024-09-06 07:14:18 字数 341 浏览 4 评论 0原文

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

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

有人可以帮我吗?

I need "get_ancestors_recursively" function.
A sample run can be

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

Can somebody help me with this ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

谜泪 2024-09-13 07:14:18

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

Another option is LXML, which provides useful extensions to the built in ElementTree api. If you're willing to install an external module, it has a nice Element.getparent() function that you could simply call recursively until reaching ElementTree.getroot(). This will probably be the fastest and most elegant solution (as the lxml.etree module introduces pointer attributes for the Elements that point to their parents, so instead of searching the entire tree for the proper parent/child pairs).

懒猫 2024-09-13 07:14:18

在最新版本的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,这很慢,并且会产生大量垃圾收集列表,但如果您可以处理它应该没问题。

In the latest version of ElementTree (v1.3 or later), you can simply do

input_element.find('..')

recursively. However, the ElementTree that ships with Python doesn't have this functionality, and I don't see anything in the Element class that looks upwards.

I believe this means you have to do it the hard way: via an exhaustive search of the element tree.

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

This is slow because of the DFS, and cranks out a lot of lists for garbage collection, but if you can deal with that it should be fine.

分开我的手 2024-09-13 07:14:18

通过大量谷歌搜索找到了这个小宝石(http://elmpowered.skawaii.net/?p=74< /a>)

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

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

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

Found this little gem from lots of googling (http://elmpowered.skawaii.net/?p=74)

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

root here is your root node of the tree. elem is the actual element object you get from iterating.

This does require you to know the root, which may mean changing how you set up for XML parsing, but it's minor at best.

弥繁 2024-09-13 07:14:18

您可以使用树遍历算法。这在线性时间内完成了任务。

def xml_get_ancestors(element: Element, root: Element):
    ancestors = []

    for node in root.iter():
        if node == element:
            return ancestors

        while len(ancestors) > 0 and node not in ancestors[-1]:
            ancestors.pop()
        
        ancestors.append(node)
    
    return None

You can use a tree traversal algorithm. This does the task in linear time.

def xml_get_ancestors(element: Element, root: Element):
    ancestors = []

    for node in root.iter():
        if node == element:
            return ancestors

        while len(ancestors) > 0 and node not in ancestors[-1]:
            ancestors.pop()
        
        ancestors.append(node)
    
    return None
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文