使用一个xpath表达式从兄弟姐妹中捕获文本

时间:2017-03-25 16:48:22

标签: xpath

假设我的HTML包含这样的内容,并且我想忽略div class=log的{​​{1}},除非前面有div class=ts,在这种情况下我想在某些数据结构中捕获兄弟div的文本内容。

一个人可以这样做,如果是的话,请问怎么样?

<div class='log'>start</div>
<div class='ts'>2017-03-14</div><div class='log'>note 1</div>
<div class='ts'>2017-03-15</div><div class='log'>note 2</div>
<div class='log'>start</div>

1 个答案:

答案 0 :(得分:2)

以下XPath返回带有div class='log'的{​​{1}},其div前面带有class='ts'

//div[@class='log' and preceding-sibling::node()[1][self::div/@class='ts']]

我打破了可能令人困惑的部分:

  • preceding-sibling::node()[1]:获取一个直接位于当前上下文元素之前的任何类型的节点(文本,元素,注释等)
  • [self::div/@class='ts']:验证该节点是divclass属性等于'ts'

从这里开始,您需要合并主机编程语言以获得所需的结果,例如,在python中使用lxml

>>> raw = '''<div>
... <div class='log'>start</div>
... <div class='ts'>2017-03-14</div><div class='log'>note 1</div>
... <div class='ts'>2017-03-15</div><div class='log'>note 2</div>
... <div class='log'>start</div>
... </div>'''
>>> from lxml import html
>>> root = html.fromstring(raw)
>>> query = "//div[@class='log' and preceding-sibling::node()[1][self::div/@class='ts']]"
>>> [[d.getprevious().text, d.text] for d in root.xpath(query)]
[['2017-03-14', 'note 1'], ['2017-03-15', 'note 2']]

以下是将根据请求返回['2017-03-14', 'note 1','2017-03-15', 'note 2']的XPath:

//div[
    (@class='log' and preceding-sibling::node()[1][self::div/@class='ts'])
        or
    (@class='ts' and following-sibling::node()[1][self::div/@class='log'])
]/text()