Python lxml XPath:前面的关键字没有给出预期的结果

时间:2015-12-02 17:46:25

标签: python xml xpath xml-parsing lxml

我正在尝试解析xml文档,如下所示

import re
from lxml.html.soupparser import fromstring

inString = """
<doc>

<q></q>

<p1>
    <p2 dd="ert" ji="pp">

        <p3>1</p3>
        <p3>2</p3>
        <p3>ABC</p3>
        <p3>3</p3>

     </p2>

     <p2 dd="ert" ji="pp">

        <p3>4</p3>
        <p3>5</p3>
        <p3>ABC</p3>
        <p3>6</p3>

     </p2>

</p1>
<r></r>
<p1>
    <p2 dd="ert" ji="pp">

        <p3>7</p3>
        <p3>8</p3>
        <p3>ABC</p3>
        <p3>9</p3>

     </p2>

     <p2 dd="ert" ji="pp">

        <p3>10</p3>
        <p3>11</p3>
        <p3>ABC</p3>
        <p3>12</p3>

     </p2>

</p1>
</doc>
"""
root = fromstring(inString)

nodes = root.xpath("./doc//p1/p2/p3[contains(text(),'ABC')]//preceding::p2//p3")

print " ".join([re.sub('[\s+]', ' ', para.text.encode('utf-8').strip()) for para in nodes])

因此,对于每个<p1>代码,我想访问<p3>内的<p2>代码。然后,我只希望<p3>标记最多标记为ABC之类的文本。但是,如果我运行上面的代码,我得到

1 2 ABC 3 4 5 ABC 6 7 8 ABC 9

期望的输出是

1 2 4 5 7 8 10 11

另外,如果我做了这个改变

nodes = root.xpath("./doc//p1/p2/p3[contains(text(),'ABC')]")

我得到了

ABC ABC ABC ABC

所以看起来第二种方法能够按照xpath从整个文档中获取所有<p3>个节点,这很好。为什么我的第一次查询不起作用?

我如何获得所需的输出?

1 个答案:

答案 0 :(得分:1)

找到包含p3的{​​{1}}后,您无需启动树 - 只需使用preceding-sibling“侧身”:

ABC

打印./doc//p1/p2/p3[contains(text(),'ABC')]/preceding-sibling::p3