python-3.x 获取包含特定文本的所有节点(文本和属性)的有效方法[重复]

7gyucuyw  于 2023-01-03  发布在  Python
关注(0)|答案(1)|浏览(172)

此问题在此处已有答案

Testing text() nodes vs string values in XPath(1个答案)
三年前关闭了。
我的目标是检索包含特定文本的所有节点。
1-我可以使用以下请求检索包含一些文本的节点:

[node for node in root.xpath('//*[contains(.,"Carte de chaleur")]') ]

Out[62]: 
[<Element workbook at 0x1818bc76e88>,
 <Element worksheets at 0x1819b886dc8>,
 <Element worksheet at 0x1819c156488>,
 <Element layout-options at 0x1819c1564c8>,
 <Element title at 0x1818e9509c8>,
 <Element formatted-text at 0x1819c156c48>,
 <Element run at 0x1818e955048>,
 <Element worksheet at 0x1819c156a88>,
 <Element layout-options at 0x1819c156fc8>,
 <Element title at 0x1818e9508c8>,
 <Element formatted-text at 0x1819c1565c8>,
 <Element run at 0x1818e955088>]

但是当我检查时,我只得到2个包含特定文本的元素。

[node for node in root.xpath('//*[contains(.,"Carte de chaleur")]') if node.text.__contains__("Carte de chaleur")]
Out[66]: [<Element run at 0x1818e955048>, <Element run at 0x1818e955088>]

事实上,当我寻找这些运行节点之一的路径时,我可以发现所有的“工作簿”、“工作表”等等......实际上都是它们的父节点。

run_node
Out[71]: <Element run at 0x1818e955048>
tree.getpath(run_node)
Out[72]: '/workbook/worksheets/worksheet[3]/layout-options/title/formatted-text/run[1]'

那么,为什么这个xpath查询返回我正在查找的节点的所有父节点(实际上只有2个run节点)呢?
2-如果我想要属性包含特定文本的节点,我运行以下查询:

root.xpath('//@*[contains(.,"bold")]/..')
Out[86]: 
[<Element format at 0x18199f56948>,
 <Element format at 0x18199f56148>]

(It的逻辑,因为我想要包含特定属性节点的节点,所以我正在查找此属性节点的父节点)
非常奇怪的是,这个请求并不产生同样的结果:

root.xpath('//*[contains(@*,"bold")]')

即使对我来说这最后一句意味着:“取任意属性包含文本“bold”的根的任何后代元素(对我来说与前一个相同)
3-我可以使用变量来检索属性包含不同值的节点吗?
对于一个变量,我可以:

root('//*[@name=$var]', var="[Petal_length]")

但是有没有一种方法可以做到:

root('//*[@name=$var1]//title[@format=$var2]', var1="[Petal_length]",var2="bold")
e5nszbig

e5nszbig1#

节点的字符串值是包含在其中的所有文本节点的串联,因此,如果一个节点在其字符串值中包含特定的子字符串,那么它的所有祖先节点也将包含该子字符串。
您的问题是希望为输入返回什么

<para>Carte <i>de</i> chaleur</para>

您是否希望返回帕拉元素?
如果您很高兴不返回这个值,那么您实际上是说所有文本必须在单个文本节点中找到,这样您就可以

//*[text()[contains(.,"Carte de chaleur")]]

如果您确实希望返回帕拉,那么您的要求是“查找包含文本的最低层元素,而不包括它们的祖先”,那么您可能必须执行类似于

//*[contains(.,"Carte de chaleur") and not(*[contains(.,"Carte de chaleur")])]

我都没开始考虑效率...

相关问题