pythonxpath:是否可以有可选的XPath查询?

2024-09-25 02:41:19 发布

您现在位置:Python中文网/ 问答频道 /正文

我有以下解析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>32</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>XYZ</p3>
        <p3>12</p3>

     </p2>

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

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

ns = {"re": "http://exslt.org/regular-expressions"}
nodes = root.xpath(".//p3[re:match(.,'XYZ') or re:match(.,'ABC')]/preceding-sibling::p3", namespaces=ns)

这让我

4 5 7 8 10 11

所以它完全跳过了第一个<p2>我的理想输出是

1 2 32 3 4 5 7 8 10 11

所以,如果我在<p2>中找不到<p3>ABC<p3><p3>XYZ<p3>,我仍然想要那<p3>的所有<p2>。有可能吗

编辑

我试过了

".//p3[re:match(.,'XYZ') or re:match(.,'ABC')]/preceding-sibling::p3 | .//p3" 

但这让我

1 2 32 3 4 5 ABC 6 7 8 ABC 9 10 11 XYZ 12

这就是一切

部分解

我试了以下方法

".//p3[re:match(.,'XYZ') or re:match(.,'ABC')]/preceding-sibling::p3 | .//p3[not (contains(text(),'ABC') or contains(text(),'XYZ'))]/preceding-sibling::p3"

这让我

1 2 32 4 5 ABC 7 8 ABC 10 11 XYZ

这是更好的,但仍然是不正确的。请注意,它缺少6,并且包含了我不想要的ABCXYZ


Tags: orrematchddppabcp2p3
1条回答
网友
1楼 · 发布于 2024-09-25 02:41:19

好的开始,那么:

.//p3[text() = 'XYZ' or text() = 'ABC']/preceding-sibling::p3 | .//p2[not(p3[text() = 'ABC' or text() = 'XYZ'])]/p3

也就是说:对于没有p3子级等于ABC或XYZ的p2,给我p3子级

(字符串等于而不是regexp,因为在本例中不需要regexp,但可以使用regexp)

相关问题 更多 >