Как получить xpathContext из xmlNode в python

Большой поклонник xpath в.net и sax в python, но впервые использовал xpath в python.

У меня есть небольшой скрипт, который использует xpath для выбора некоторых узлов в документе, выполняет итерацию по ним, а затем в идеале снова использует xpath для получения соответствующих данных из них. Однако я не могу получить этот последний бит, когда у меня есть xmlNode, я не могу получить контекст из него.

import libxml2
import urllib

doc = libxml2.parseDoc(
        urllib.urlopen('http://somemagicwebservice.com/').read())
ctxt = doc.xpathNewContext()
listitems = ctxt.xpathEval('//List/ListItem')
for item in listitems:
    itemctxt = item.xpathNewContext()
    title = itemctxt.xpathEval('//ItemAttributes/Title')
    asin = itemctxt.xpathEval('//Item/ASIN')
    itemctxc.xpathFreeContext()
ctxt.xpathFreeContext()
doc.freeDoc()

Тем не менее itemctxt = item.xpathNewContext() бит терпит неудачу с

itemctxt = item.xpathNewContext()
AttributeError: xmlNode instance has no attribute 'xpathNewContext'

Любые идеи, как использовать xpath на xmlNode? Я не могу найти хорошую информацию онлайн. Спасибо

2 ответа

Решение

Я не думаю, что XPathContext имеет смысл для элемента? Попробуйте создать новый XPathContext и установить для его узла текущий элемент.

Тем не менее, я не использовал libxml2 напрямую, так что это немного дикое предположение. Обычно я использую lxml, который предоставляет API ElementTree вокруг libxml2 и libxslt. Его гораздо проще использовать, и он действительно разрешает xpath() для элементов. Конечно, если у вас уже есть много кода, использующего libxml2, вы, вероятно, не хотите переключаться, но в этом случае вы можете взглянуть на исходный код lxmls, чтобы увидеть, как он это делает.

http://codespeak.net/svn/lxml/trunk/src/lxml/xpath.pxi

http://codespeak.net/svn/lxml/trunk/src/lxml/_elementpath.py

Кажется, хорошие стартовые места.

/questions/7607984/python-i-libxml2-kak-vyipolnyat-iteratsii-v-uzlah-xml-s-xpath/7607996#7607996 предлагает позвонить setContextNode(..) на вновь созданном контексте:

itemctxt = doc.xpathNewContext()

for item in listitems:
    itemctxt.setContextNode(item)
    title = itemctxt.xpathEval('.//ItemAttributes/Title')

    ...

itemctxt.xpathFreeContext()

В версии Python libxml (2.9.1), которую я сейчас использую, оказывается, что можно даже вызвать:

item.xpathEval('.//ItemAttributes/Title')

Обратите внимание, что вам нужно добавить точку в начале выражений xpath .// (вместо //), иначе вы получите результаты поиска относительно корня документа.

Другие вопросы по тегам