ElementTree XPath - Выбрать элемент на основе атрибута

StackOverflow https://stackoverflow.com/questions/222375

  •  03-07-2019
  •  | 
  •  

Вопрос

У меня возникли проблемы с использованием атрибута XPath Selector в ElementTree, что я должен быть в состоянии сделать в соответствии с Документация

Вот несколько примеров кода

XML

<root>
 <target name="1">
    <a></a>
    <b></b>
 </target>
 <target name="2">
    <a></a>
    <b></b>
 </target>
</root>

Питон

def parse(document):
    root = et.parse(document)
    for target in root.findall("//target[@name='a']"):
        print target._children

Я получаю следующее исключение:

expected path separator ([)
Это было полезно?

Решение

Синтаксис, который вы пытаетесь использовать, является новым в Дерево элементов 1.3.

Такая версия поставляется с Python 2.7 или выше.Если у вас есть Python 2.6 или меньше, у вас все еще есть ElementTree 1.2.6 или меньше.

Другие советы

В этом коде есть несколько проблем.

  1. Python buildin ElementTree (сокращенно ET) не имеет реальной поддержки XPATH;только ограниченное подмножество По примеру, оно не поддерживает найти-из-корня такие выражения , как //target.

    УВЕДОМЛЕНИЕ:тот самый Документация упоминания "//", но только для детей:Таким образом, выражение в виде .//target является действительным; //... это не так!

    Существует альтернативная реализация: lxml который более богат.Хорошо, что используется документация для встроенного кода.Это не соответствует / не работает.

  2. Тот самый @name обозначение выбирает xml-атрибуты;тот самый key=value выражение внутри xml-тега.

    Таким образом, это значение name должно быть равно 1 или 2, чтобы выбрать что-то в данном документе.Или же можно искать цели вместе с ребенком элемент "а": target[a] (нет @).

Для данного документа, проанализированного с помощью встроенного ElementTree (версия v1.3) до root, следующий код является правильным и работающим:

  • root.findall(".//target") Найдите обе цели
  • root.findall(".//target/a") Найдите два a-элемента
  • root.findall(".//target[a]") Это снова находит оба целевых элемента, поскольку у обоих есть a-элемент
  • root.findall(".//target[@name='1']") Найдите только тот Первый цель.Обратите внимание, что необходимы кавычки около 1;в противном случае возникает ошибка SyntaxError
  • root.findall(".//target[a][@name='1']") Также действителен;чтобы найти эту цель
  • root.findall(".//target[@name='1']/a") Находит только один a-элемент;...
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top