我有以下HTML代码,其中包含一个地址:
<html>
<body>
<div>
<h2>Address</h2>
<p>
Rotes Rathaus<br />
Rathausstrasse<br />
10178 Berlin<br />
Germany<br />
</p>
</div>
</body>
</html>
我试图找到包装地址的段落节点(在我的例子中:<p>
标签),而我所拥有的只是地址部分的数组(例如:&# 39; Rathaus&#39;,&#39; Berlin&#39;&#39; 10178&#39;)。
我使用以下XPath选择器查询dom:
//*[contains(text(),'Rathaus')]
这很有效,返回符合
节点。但是,当我根据邮政编码查看时,我没有得到任何匹配:
//*[contains(text(),'10178')]
为了解决这个问题,我需要做什么? 请注意,地址的位置可以在页面的任何位置。
祝你好运, 尼古拉斯
答案 0 :(得分:3)
<强>解决方案强>
使用
//*[text()[contains(.,'10178')]]
将选择p
元素作为结果。这意味着
在文档中的任何位置查找任何元素节点,但前提是至少有一个子文本节点,其字符串值包含&#34; 10178&#34;。
另一方面,您的原始表达:
//*[contains(text(),'10178')]
表示:
在文档中的任何位置查找任何元素节点,但前提是其子文本节点的第一个包含字符串&#34; 10178&#34;。
<强>解释强>
由于函数在XPath 1.0中的工作方式,您对结果感到惊讶。像contains()
这样的函数需要单个节点作为第一个参数。如果它被传递给一组节点,它将只处理第一个节点并忽略其余节点。
您需要了解的另一件事是,由子元素分隔的文本最终会出现在单独的文本节点中。因此,P
的文本内容实际上被切割成了几个文本节点,因为插入了br
元素。
你可以通过评估像
这样的表达来检查这一点//p/node() | Find `p` elements anywhere in the document and return all nodes
that are their children, regardless of the type of node.
在您显示的文档上,它将返回(单个结果以-------
分隔):
Rotes Rathaus
-----------------------
<br/>
-----------------------
Rathausstrasse
-----------------------
<br/>
-----------------------
10178 Berlin
-----------------------
<br/>
-----------------------
Germany
-----------------------
<br/>
-----------------------
如您所见,只要p
之间存在br
,//p/text()[3]
的文本内容就会存储在单独的文本节点中。在这一点上你应该意识到,如果&#34; 10178&#34;碰巧是在第一个文本节点中,而不是第三个。也许你可以猜出{{1}}会产生什么?
最后提示:这与XPath 2.0一起发生变化,其中多个项目是真正的节点序列,其中函数将依次处理每个节点。