Главная | Обратная связь | Поможем написать вашу работу!
МегаЛекции

Поиск узлов в XML документе




До настоящего момента мы рассматривали XML документ «сверху вниз», начиная с корневого элемента, далее к его дочерним элементы и так вглубь всего документа. Однако во многих случаях при работе с XML Вам необходимо искать конкретные элементы. Etree справится и с этой задачей.

> > > import xml. etree. ElementTree as etree> > > tree = etree. parse('examples/feed. xml')> > > root = tree. getroot()> > > root. findall('{http: //www. w3. org/2005/Atom}entry') ① [< Element {http: //www. w3. org/2005/Atom}entry at e2b4e0>, < Element {http: //www. w3. org/2005/Atom}entry at e2b510>, < Element {http: //www. w3. org/2005/Atom}entry at e2b540> ]> > > root. tag'{http: //www. w3. org/2005/Atom}feed'> > > root. findall('{http: //www. w3. org/2005/Atom}feed') ② []> > > root. findall('{http: //www. w3. org/2005/Atom}author') ③ []

① Метод findall() выполняет поиск дочерних элементов удовлетворяющих запросу. (Формат запроса рассматривается ниже. )

② Все элементы (включая корневой и дочерние) имеют метод findall(). Метод находит все элементы среди дочерних соответствующие запросу. Почему же метод вернул пустой список? Хотя это может показаться неочевидным, данный запрос ищет только в дочерних элементах. Так как корневой элемент feed не имеет дочерних элементов по имени feed, то запрос возвращает пустой список.

③ Этот результат также может Вас удивить. В документе XML действительно есть элемент author; на самом деле, их даже три (по одному в каждом элементе entry). Но эти элементы author не являются прямыми подэлементами (direct children) корневого элемента; они — «подподэлементы» (подэлементы подэлемента). Если Вам нужно найти элементы author любого уровня вложенности, то придётся изменить строку запроса.

> > > tree. findall('{http: //www. w3. org/2005/Atom}entry') ① [< Element {http: //www. w3. org/2005/Atom}entry at e2b4e0>, < Element {http: //www. w3. org/2005/Atom}entry at e2b510>, < Element {http: //www. w3. org/2005/Atom}entry at e2b540> ]> > > tree. findall('{http: //www. w3. org/2005/Atom}author') ② []

① Для удобства объект tree (который возвращает функция etree. parse()) имеет несколько методов идентичных методам корневого элемента. Результаты функции такие же как при вызове метода tree. getroot(). findall().

② Наверное, удивлены, однако этот запрос не находит элемента author в данном документе. Почему же? Потому что, этот вызов идентичен вызову tree. getroot(). findall('{http: //www. w3. org/2005/Atom}author'), что значит «найти все элементы author, которые являются подэлементами корневого элемента». Элементы author не являются дочерними для корневого элемента; они подэлементы элементов entry. Таким образом, при выполнении запроса совпадений не найдено.

Помимо метода findall() есть метод find() который возвращает только первый найденный элемент. Метод может быть полезен в случаях когда в результате поиска Вы ожидаете только один элемент или Вам важен только первый элемент из списка найденных.

> > > entries = tree. findall('{http: //www. w3. org/2005/Atom}entry')      ① > > > len(entries)3> > > title_element = entries[0]. find('{http: //www. w3. org/2005/Atom}title') ② > > > title_element. text'Dive into history, 2009 edition'> > > foo_element = entries[0]. find('{http: //www. w3. org/2005/Atom}foo') ③ > > > foo_element> > > type(foo_element)< class 'NoneType'>

① Как Вы видели в предыдущем примере findall() возвращает список элементов atom: entry.

② Метод find() принимает запрос ElementTree и возвращает первый удовлетворяющий запросу элемент.

③ Во элементе foo отсутствуют дочерние элементы, поэтому find() возвращает объект None.

Здесь необходимо отметить закавыку при использовании метода find(). В логическом контексте объекты элементов ElementTree не содержащие дочерних элементов равны значению False (т. е if len(element) вычисляется как 0). Код if element. find('... ') проверяет не то, что нашёл ли метод find() удовлетворяющий запросу элемент; код проверяет содержит ли найденный элемент дочерние элементы! Для того чтобы проверить нашёл ли метод find() элемент необходимо использовать if element. find('... ') is not None.

Рассмотрим поиск внутри дочерних элементов, т. е подэлементов, подподэлементов и так далее любого уровня вложенности.

> > > all_links = tree. findall('//{http: //www. w3. org/2005/Atom}link') ① > > > all_links[< Element {http: //www. w3. org/2005/Atom}link at e181b0>, < Element {http: //www. w3. org/2005/Atom}link at e2b570>, < Element {http: //www. w3. org/2005/Atom}link at e2b480>, < Element {http: //www. w3. org/2005/Atom}link at e2b5a0> ]> > > all_links[0]. attrib                                         ② {'href': 'http: //diveintomark. org/', 'type': 'text/html', 'rel': 'alternate'}> > > all_links[1]. attrib                                         ③ {'href': 'http: //diveintomark. org/archives/2009/03/27/dive-into-history-2009-edition', 'type': 'text/html', 'rel': 'alternate'}> > > all_links[2]. attrib{'href': 'http: //diveintomark. org/archives/2009/03/21/accessibility-is-a-harsh-mistress', 'type': 'text/html', 'rel': 'alternate'}> > > all_links[3]. attrib{'href': 'http: //diveintomark. org/archives/2008/12/18/give-part-1-container-formats', 'type': 'text/html', 'rel': 'alternate'}

① Этот запрос — //{http: //www. w3. org/2005/Atom}link — очень похож на запросы из предыдущих примеров. Отличие заключается в двух символах косой черты // в начале строки запроса. Символы // обозначают «Я хочу найти все элементы независимо от уровня вложенности, а не только непосредственные дочерние элементы». Поэтому метод возвращает список из четырёх элементов, а не из одного.

② Первый элемент результата — прямой подэлемент корневого элемента. Как мы видим из его атрибутов, это альтернативная ссылка уровня фида, которая указывает на html версию вебсайта на котором располагается фид.

③ Остальные три элемента результата есть альтернативные ссылки уровня элементов entry. Каждый из элементов entry имеет по одному подэлементу link. Так как запрос findall() содержал символы двойной черты в начале запроса, то результат поиска содержит все подэлементы link.

В целом, метод findall() библиотеки ElementTree довольно мощный инструмент поиска, однако формат запроса может быть немного непредсказуем. Официально формат запросов ElementTree описан как «ограниченная поддержка выражений XPath». XPath это стандарт организации W3C для построения запросов поиска внутри XML документа. С одной стороны формат запросов ElementTree достаточно похож на формат XPath для выполнения простейших поисков. С другой стороны он отличается настолько, что может начать раздражать если Вы уже знаете XPath. Далее мы рассмотрим сторонние библиотеки XML позволяющие расширить API ElementTree до полной поддержки стандарта XPath.

Поделиться:





Воспользуйтесь поиском по сайту:



©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...