ElementTree XPath - Выбрать элемент на основе атрибута
-
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 или меньше.
Другие советы
В этом коде есть несколько проблем.
Python buildin ElementTree (сокращенно ET) не имеет реальной поддержки XPATH;только ограниченное подмножество По примеру, оно не поддерживает найти-из-корня такие выражения , как
//target
.УВЕДОМЛЕНИЕ:тот самый Документация упоминания "//", но только для детей:Таким образом, выражение в виде
.//target
является действительным;//...
это не так!Существует альтернативная реализация: lxml который более богат.Хорошо, что используется документация для встроенного кода.Это не соответствует / не работает.
Тот самый
@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;в противном случае возникает ошибка SyntaxErrorroot.findall(".//target[a][@name='1']")
Также действителен;чтобы найти эту цельroot.findall(".//target[@name='1']/a")
Находит только один a-элемент;...