2010-06-14 4 views
1

Мне нужна функция "get_ancestors_recursively".
Образец выполнения можетВ Python ElementTree как я могу получить список всех предков элемента в дереве?

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

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

ответ

1

В последней версии 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 

Это медленно из-за ДПП, и проворачивает много списков для сбора мусора, но если вы можете иметь дело с этим она должна быть тонкой.

2

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

+0

Да: используйте lxml, а затем вы можете вызвать elem.getparent() рекурсивно для обхода дерева, или вы можете использовать elem.xpath ('ancestor :: *') и получить список узлов-предков напрямую. (xpath работает с любым узлом как узлом контекста, а не только с корнем документа). –

0

Найдено этот маленький драгоценный камень от многих прибегая к помощи (http://elmpowered.skawaii.net/?p=74)

родителя = root.findall (".// {0}/.." формат (elem.tag).)

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

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

 Смежные вопросы

  • Нет связанных вопросов^_^