首页 > 解决方案 > 获取包含特定文本的所有节点(文本和属性)的有效方法

问题描述

我的目标是检索包含特定文本的所有节点。

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 个运行节点)?

2-如果我想要其属性包含特定文本的节点,我运行此查询:

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

(这是逻辑,因为我想要包含特定属性节点的节点,所以我正在寻找这个属性节点的父节点)

很奇怪,这个请求不会产生相同的结果:

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

即使对我来说这最后一个意思是:“取根的任何属性包含文本“粗体”的任何后代元素(与我的前一个相同)

3-我可以使用变量检索属性包含不同值的节点吗?

对于一个变量,我可以这样做:

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

但是有没有办法做类似的事情:

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

编辑:这是原文https://ctxt.io/2/AACATwNVFA。Ps:如果有人知道分享一些文字超过 1 天的方法,那将对我有所帮助。

标签: python-3.xxmlxpath

解决方案


节点的字符串值是其中包含的所有文本节点的串联,因此如果一个节点在其字符串值中包含特定的子字符串,那么它的所有祖先也会这样做。

你的问题是你想要为输入返回什么

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

您是否希望返回 para 元素?

如果您对此不返回感到高兴,那么您实际上是在说必须在单个文本节点中找到所有文本,所以您可以这样做

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

如果您确实希望返回 para,因此您的要求是“找到包含文本的最低级别元素,而不包括它们的祖先”,那么您可能需要执行类似的操作

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

我什至没有开始考虑这里的效率......


推荐阅读