2010-01-31 5 views
43

Я использую встроенный модуль Python ElementTree. Прямо получить доступ к детям, но как относиться к родительским или родственным узлам? - можно ли это сделать эффективно, не пройдя по всему дереву?Доступ к родительскому узлу узла ElementTree

+1

См http://stackoverflow.com/questions/374245/how-to-retrieve-the-parent-node-using- celementtree – kennytm

ответ

33

Нет прямой поддержки в виде атрибута parent, но вы можете использовать шаблоны, описанные here, для достижения желаемого эффекта. Следующий один вкладыш предлагается (от связного к сообщению), чтобы создать отображение ребенка к родителю для всего дерева:

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

Обновление синтаксиса, 2017/python3 'parent_map = {(c, p) для p в дереве.iter() для c in p} ' – gerardw

+1

Исправление: ' parent_map = {c: p для p в root.iter() для c in p} ' – gerardw

14

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 
+1

Что делать, если у вас нет доступа к дереву? Как и после .find() – Brett

+1

Я не знаю, как получить корневой узел (и, следовательно, родителей/предков), если вы не сохранили ссылку на него. Но я не понимаю, как '.find()' имеет к этому какое-то отношение. – supergra

+0

Я просто использовал '.find()' как примерную функцию, которая просто возвращает элемент – Brett

2

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

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

Не работает для меня, я получаю «None» - то же самое, если я просто использую 'subElement.find ('..')'. – damian

1

Если вы используете LXML, я был в состоянии получить родительский элемент со следующим:

parent_node = next(child_node.iterancestors()) 

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

4

Вы можете использовать обозначение xpath ... в ElementTree.

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

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

Это фантастическое решение, работает с find(), также, если вы знаете, что есть только один элемент, который вы ищете. Например: 'root.find (" .//*[@ testname = 'generated_sql'] ... ")' – Bostone

3

Как уже упоминались в Get parent element after using find method (xml.etree.ElementTree) вы должны сделать косвенный поиск родителей. Имея XML:

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

Предполагая, что вы создали etree элемента в xml переменных, вы можете использовать:

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>

1

Посмотрите на пункт 19.7.2.2. Раздел: Supported XPath syntax ... Родитель

Найти узла, используя путь:

parent_node = node.find('..') 
+1

Вы проверили это? Если вы смогли заставить его работать, отправьте полный пример кода, который демонстрирует его. См. Этот комментарий: https://stackoverflow.com/questions/2170610/access-elementtree-node-parent-node#comment44519212_21963494 – mzjn

+1

Документация Python 3 гласит: «Возвращает« Нет », если путь пытается достичь предков начала элемент (вызывается элемент 'find')." (Https://docs.python.org/3/library/xml.etree.elementtree.html#supported-xpath-syntax). – mzjn

+0

Работает для меня. Самый лучший и самый частый ответ. – ToTenMilan

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