Как сопоставить текстовый узел, затем следовать родительским узлам, используя XPath - PullRequest
14 голосов
/ 01 марта 2009

Я пытаюсь разобрать HTML с XPath. Следуя приведенному ниже упрощенному примеру XML, я хочу сопоставить строку «Текст 1», а затем получить содержимое соответствующего узла content.

<doc>
    <block>
        <title>Text 1</title>
        <content>Stuff I want</content>
    </block>

    <block>
        <title>Text 2</title>
        <content>Stuff I don't want</content>
    </block>
</doc>

Мой код Python вызывает колебание:

>>> from lxml import etree
>>>
>>> tree = etree.XML("<doc><block><title>Text 1</title><content>Stuff 
I want</content></block><block><title>Text 2</title><content>Stuff I d
on't want</content></block></doc>")
>>>
>>> # get all titles
... tree.xpath('//title/text()')
['Text 1', 'Text 2']
>>>
>>> # match 'Text 1'
... tree.xpath('//title/text()="Text 1"')
True
>>>
>>> # Follow parent from selected nodes
... tree.xpath('//title/text()/../..//text()')
['Text 1', 'Stuff I want', 'Text 2', "Stuff I don't want"]
>>>
>>> # Follow parent from selected node
... tree.xpath('//title/text()="Text 1"/../..//text()')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "lxml.etree.pyx", line 1330, in lxml.etree._Element.xpath (src/
lxml/lxml.etree.c:14542)
  File "xpath.pxi", line 287, in lxml.etree.XPathElementEvaluator.__ca
ll__ (src/lxml/lxml.etree.c:90093)
  File "xpath.pxi", line 209, in lxml.etree._XPathEvaluatorBase._handl
e_result (src/lxml/lxml.etree.c:89446)
  File "xpath.pxi", line 194, in lxml.etree._XPathEvaluatorBase._raise
_eval_error (src/lxml/lxml.etree.c:89281)
lxml.etree.XPathEvalError: Invalid type

Возможно ли это в XPath? Нужно ли выражать то, что я хочу сделать, по-другому?

Ответы [ 2 ]

23 голосов
/ 01 марта 2009

Ты этого хочешь?

//title[text()='Text 1']/../content/text()
16 голосов
/ 01 марта 2009

Используйте

string(/*/*/title[. = 'Text 1']/following-sibling::content)

Это представляет как минимум два улучшения по сравнению с принятым в настоящее время решением Йоханнеса Вайса:

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

  2. Нет возврата к родительскому элементу (шаг определения местоположения "/ .." исключается)

...