В Python ElementTree, как я могу получить список всех предков элемента в дереве? - PullRequest
1 голос
/ 15 июня 2010

Мне нужна функция "get_ancestors_recursively".
Примерный прогон может быть

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

Может ли кто-нибудь помочь мне с этим?

Ответы [ 3 ]

3 голосов
/ 17 июня 2010

Другой вариант - LXML , который предоставляет полезные расширения для встроенного API ElementTree. Если вы хотите установить внешний модуль, он имеет замечательную функцию Element.getparent(), которую вы можете просто вызывать рекурсивно, пока не достигнете ElementTree.getroot(). Вероятно, это будет самое быстрое и элегантное решение (поскольку lxml.etree module вводит атрибуты указателя для элементов, указывающих на их родителей, поэтому вместо поиска по всему дереву правильных пар parent/child).

1 голос
/ 15 июня 2010

В последней версии ElementTree (v1.3 или новее) вы можете просто сделать

input_element.find('..')

рекурсивно. Однако ElementTree, поставляемый с Python, не имеет этой функциональности, и я не вижу ничего в классе 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 и запускает множество списков для сборки мусора, но если вы справитесь с этим, все будет хорошо.

0 голосов
/ 15 июня 2015

Нашел этот маленький драгоценный камень из множества поисковиков (http://elmpowered.skawaii.net/?p=74)

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

корень здесь - это ваш корневой узел дерева. elem - это фактический элемент элемента, который вы получаете из итерации.

Это требует от вас знания корня, что может означать изменение настроек для синтаксического анализа XML, но в лучшем случае оно незначительное.

...