2008-10-21 3 views
36

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

Вот некоторые примеры кода

XML

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

Python

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

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

expected path separator ([) 
+1

Используя ElementTree 1.2.6, атрибуты xpath доступны только в версии 1.3 и выше. – 2008-10-21 16:14:00

ответ

33

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

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

3

Похоже FindAll поддерживает только подмножество XPath. См. Рассылку списка here

10

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

  1. Элегантный элемент ElementTree (ET для краткости) не имеет реальной поддержки XPATH; только ограниченное подмножество. Например, оно не поддерживает find-from-root выражения типа //target.

    Извещение: documentation упоминает «//», но только для детей: Так выражение, как .//target действует; //... нет!

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

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

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

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

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