2009-07-05 3 views
2

большой поклонник xpath на .net и sax в python, но сначала использует xpath в python.Как получить xpathContext из xmlNode в 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? Я не могу найти хорошую онлайн-информацию. Thanks

ответ

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

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

+0

Ну, у меня были схожие проблемы с lxml, но, оказывается, проблема была связана с тем, как xpath имеет дело с пространствами имен. Элемент Path от lxml упростил ситуацию. Благодарю. – Kurt

+0

Если кто-то хочет посмотреть, что у меня получилось, ознакомьтесь с https://bitbucket.org/kurthaeusler/getwishlist/src/tip/getwishlist.py – Kurt

1

https://stackoverflow.com/a/3379708/288875 предлагает назвать setContextNode(..) на вновь созданном контексте:

itemctxt = doc.xpathNewContext() 

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

    ... 

itemctxt.xpathFreeContext() 

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

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

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