Python 如何匹配文本节点,然后使用XPath跟踪父节点

Python 如何匹配文本节点,然后使用XPath跟踪父节点,python,html,xpath,lxml,Python,Html,Xpath,Lxml,我正在尝试用XPath解析一些HTML。下面是简化的XML示例,我想匹配字符串“Text 1”,然后获取相关内容节点的内容 <doc> <block> <title>Text 1</title> <content>Stuff I want</content> </block> <block> <title>Text

我正在尝试用XPath解析一些HTML。下面是简化的XML示例,我想匹配字符串“Text 1”,然后获取相关
内容
节点的内容

<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>

文本1
我想要的东西
文本2
我不想要的东西
我的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
来自lxml导入etree的
>>
>>>
>>>tree=etree.XML(“Text 1Stuff
我想要下一张2英镑的票
“我不想要”
>>>
>>>#获得所有头衔
... xpath(“//title/text()”)
[‘文本1’、‘文本2’]
>>>
>>>#匹配“文本1”
... xpath(“//title/text()=”text 1“)
真的
>>>
>>>#从选定节点跟随父节点
... xpath('//title/text()/../../..//text()'))
[“文本1”、“我想要的”、“文本2”、“我不想要的”]
>>>
>>>#从所选节点跟随父节点
... xpath('//title/text()=“text 1”/.././/.text()”)
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
lxml.etree.\u Element.xpath(src)中的文件“lxml.etree.pyx”,第1330行/
lxml/lxml.etree.c:14542)
lxml.etree.XPathElementEvaluator中的文件“xpath.pxi”,第287行
(src/lxml/lxml.etree.c:90093)
文件“xpath.pxi”,第209行,在lxml.etree.\u xpatheevaluorbase.\u handl
e_结果(src/lxml/lxml.etree.c:89446)
文件“xpath.pxi”,第194行,在lxml.etree.\u xpatheevaluorbase.\u
_评估错误(src/lxml/lxml.etree.c:89281)
lxml.etree.xpathevaleror:无效类型
这在XPath中可能吗?我需要用不同的方式表达我想做的事情吗?

你想要吗

//title[text()='Text 1']/../content/text()
使用

string(/*/*/title[. = 'Text 1']/following-sibling::content)
与Johannes Weiß目前接受的解决方案相比,这至少有两个改进:

  • 避免使用非常昂贵的缩写“/”(通常导致扫描整个XML文档),因为只要事先知道XML文档的结构,就应该这样做

  • 不会返回到父级(避免定位步骤“/…”)


  • 嗯,真的很简单!我现在选择text()属性有点道理。您也可以使用//block[title='text 1']/content来获取相关内容node@Dror:现在知道这一点很有用。公平的改进,我的实际文档是HTML,“标题”部分嵌套了大约五层,所以我必须回到大约五位家长那里才能进入“内容”区域。我会记住第一点,尽管这对一个肮脏的黑客来说没有什么区别。
    /*/*/
    做什么?我正在一个相当大的文档上尝试它,它看起来很慢,就像
    //
    @dentarg:
    /*/*
    选择文档顶部元素的所有子元素一样。它比遍历整个文档并选择名为“someName”
    的每个元素的
    /someName
    要快得多。在这个答案中,我们可以使用一个更高效的表达式:
    string(/*/*/title[.='Text 1'][1]/following sibling::content)
    如果有一个优化良好的XPath处理器,那么答案中的表达式的效率应该不会更低——因为每当
    string()
    函数提供一个作为节点集的参数时,它仅生成此节点集的第一个节点的字符串值。