Python XpathEvaluator без пространства имен

Мне нужно написать динамическую функцию, которая находит элементы в поддереве XML-документа ATOM.

Для этого я написал что-то вроде этого:

    tree = etree.parse(xmlFileUrl)
    e = etree.XPathEvaluator(tree, namespaces={'def':'http://www.w3.org/2005/Atom'})
    entries = e('//def:entry')
    for entry in entries:
        mypath = tree.getpath(entry) + "/category"
        category = e(mypath)

Приведенный выше код не может найти категорию.

Причина в том, что getpath возвращает XPath без пространств имен, тогда как XPathEvaluator e() требует пространств имен.

Есть ли способ либо заставить getpath возвращать пространства имен в пути, либо разрешить XPathEvaluator принимать путь без указания пространства имен (или, скорее, указав его каким-то другим способом)?


person puntofisso    schedule 26.10.2012    source источник


Ответы (1)


Использование:

*[local-name() = 'category']

Or, if you want to be more precise:

*[local-name() = 'category' and namespace-uri() = 'http://www.w3.org/2005/Atom']

Или просто:

def:category
person Dimitre Novatchev    schedule 26.10.2012
comment
Не понимаю, как это помогает решить проблему. - person puntofisso; 29.10.2012
comment
@puntofisso, самый простой способ увидеть - это попробовать. - person Dimitre Novatchev; 29.10.2012
comment
Хорошо, извините, мой комментарий был немного резким (и я думал, что не опубликовал его: P). Вопрос в другом: что, если я хочу построить этот путь динамически? Есть ли шанс это сделать? Спасибо за помощь @dimitre-novachev - person puntofisso; 29.10.2012
comment
@puntofisso, существует множество способов динамического построения выражения XPath (которое само по себе является просто строкой). Необходимо знать, известна ли какая-либо информация о XML-документе заранее (статически) и какие части скелета выражения XPath должны генерироваться динамически. Поскольку это совершенно не упоминается в текущем вопросе, было бы хорошо, если бы вы задали новый отдельный вопрос SO. - person Dimitre Novatchev; 29.10.2012
comment
На самом деле, @Dimitre, в ответе есть проблема. Допустим, я делаю, как вы говорите, и выполняю поиск category = e('*[local-name() = category]') внутри цикла for. Проблема с оценщиком в том, что он ищет в корне. Как я могу заставить его искать только текущую запись в цикле for? Вот почему мне нужно было построить xpath автоматически, в основном, если нет способа вызвать e() только при входе. - person puntofisso; 30.10.2012
comment
@puntofisso, это относительное выражение XPath, поэтому оно будет искать в корне только в том случае, если корень является текущим узлом, от которого оценивается выражение XPath. Итак, вам нужно сделать что-то вроде этого (извините, я не знаю Python): entry.whateverEvaluateMethod(*[local-name() = 'category']) . Здесь entry должен быть узлом, от которого вы хотите, чтобы выражение Xpath оценивалось. - person Dimitre Novatchev; 30.10.2012
comment
Да, точно. Мне не хватает этого whatEvaluateMethod :) Думаю, я использую библиотеку без особых удобных функций для Xpath. - person puntofisso; 30.10.2012
comment
@puntofisso, почти в каждом языке программирования есть такая функция / метод - я считаю, что нужно просто поискать соответствующую документацию. - person Dimitre Novatchev; 30.10.2012
comment
@puntofisso, я не знаю Python. Я могу сказать вам, что в C# есть метод XNode.XPathEvaluate(), который возвращает object, а вызывающая программа приводит его к ожидаемому объекту ype — int, decimal, double, bool или XmlNodeList. Аналогичный метод XPathNavigator.Evaluate() . Я видел на SO примеры кода Java, показывающие использование аналогичного метода в Java. Я сделал быстрый поиск и нашел это: lxml.de/xpathxslt.html#xpath . Там сказано: когда xpath() используется для элемента, выражение XPath оценивается для элемента (если относительно) или для корневого дерева (если абсолютно) - person Dimitre Novatchev; 01.11.2012