Есть ли более питонный способ доступа к дочерним элементам родителей с помощью lxml - PullRequest
1 голос
/ 24 июня 2010

Я копаюсь в документах XBRL, пытаясь понять, как эффективно извлекать и использовать данные.Одна вещь, с которой я боролся, - это убедиться, что я правильно использую контекстную информацию.Ниже приведен фрагмент одного из документов, с которыми я играю (это из последней версии 10-K Mattel)

Я хочу иметь возможность эффективно собирать пары значений ключей контекста, поскольку они важны для выравнивания'реальные' данные 'Вот пример элемента контекста

- <context id="eol_PE6050----0910-K0010_STD_0_20091231_0">
  - <entity>
     <identifier scheme="http://www.sec.gov/CIK">0000063276</identifier> 
   </entity>
  - <period>
   <instant>2009-12-31</instant> 
   </period>
   </context>

Когда я начал это, я подумал, что если бы были отношения родитель-потомок, я мог бы получить атрибуты, ключи, значения итекст всех детей непосредственно от применения метода (?) к родителю.Но дети сохраняют свою независимость, хотя их можно найти у родителей.Я имею в виду, что если у дочерних элементов есть атрибуты, ключи, значения и / или текст, к этим конструкциям нельзя напрямую получить доступ из родительского элемента, вместо этого вы должны определить / идентифицировать дочерние элементы и из дочерних элементов получить доступ к необходимым данным или метаданным.

Я не совсем уверен, почему этот блок кода является хорошей отправной точкой:

 from lxml import etree
 test_tree=etree.parse(r'c:\temp\test_xml\mat-20091231.xml')
 tree_list=[p for p in test_tree.getiterator() 

, поэтому мой tree_list представляет собой список элементов, которые были определены в моем XML-файле
Поскольку в моем tree_list было всего 664 элемента, я очень ошибочно предположил, что все элементы в родительском элементе были отнесены к родительскому элементу, поэтому я продолжал пытаться получить доступ к сущности, периоду и моменту, ссылаясь только на эти элементы (а не на их дочерние элементы).

for each in tree_list:
    if 'context' in each.tag:
        contextlist.append(each)

То есть я продолжал применять различные методы к элементам в контекстном списке и был действительно разочарован.Наконец, когда я писал вопрос, я пытался получить некоторую помощь в выяснении, какой метод даст мне сущность и период, я просто решил попробовать

children=[c for c in contextlist[0].iterchildren()]

, чтобы в моем списке детей были все дети изпервый элемент в моем контекстном списке

Один из дочерних элементов является элементом сущности, а другой - элементом периода

Теперь необходимо, чтобы у каждого из этих дочерних элементов был дочерний элемент сущности.имеет дочерний элемент идентификатора, а элемент period имеет мгновенный дочерний элемент. Это становится намного сложнее, чем казалось сегодня утром.

Мне нужно знать детали, которые сообщаются элементами контекста, чтобы правильно оценивать реальные данные и работать с ними.Кажется, мне нужно проверить каждого из дочерних элементов контекста. Есть ли более быстрый и эффективный способ получить эти значения?Перефразируя, есть ли способ иметь некоторый элемент и создать структуру данных, которая содержит всех его дочерних элементов, внуков и т. Д. Без необходимости делать изрядное количество операторов try else

Как только они у меня появятся, я могу начать строитьсловарь данных и назначить элементы данных для конкретных записей на основе контекста.Поэтому эффективное и полное получение элементов контекста имеет решающее значение для моей задачи.

1 Ответ

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

Используя интерфейс дерева элементов (который также поддерживает lxml), getiterator выполняет итерации по всем узлам в поддереве с корнем в текущем элементе.

Итак, [list(c.getiterator()) for c in contextlist] дает вамсписок списков, который вы хотите (или, возможно, вы захотите сохранить c в результирующем списке, чтобы избежать необходимости позднее архивировать его с помощью contextlist, т. е. напрямую составлять список кортежей [(c, list(c.getiterator())) for c in contextlist], в зависимости от вашего предполагаемого использования).

Обратите внимание, что listcomp точной формы [x for x in whatever] никогда не имеет особого смысла - вместо этого используйте list(whatever), чтобы превратить все другие итерируемые в список.

...