我尝试将SimpleXML与XPath结合使用,以查找包含特定字符串的节点。
<?php
$xhtml = <<<EOC
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="de" lang="de">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>Test</title>
</head>
<body>
<p>Find me!</p>
<p>
<br />
Find me!
<br />
</p>
</body>
</html>
EOC;
$xml = simplexml_load_string($xhtml);
$xml->registerXPathNamespace('xhtml', 'http://www.w3.org/1999/xhtml');
$nodes = $xml->xpath("//*[contains(text(), 'Find me')]");
echo count($nodes);
预期产量:2 实际输出:1
当我将第二段的xhtml更改为
时<p>
Find me!
<br />
</p>
然后它就像预期的那样工作。我的XPath表达式如何匹配包含“Find me”的所有节点,无论它们在哪里?
使用PHP的DOM-XML是一种选择,但不是必需的。
提前感谢!
答案 0 :(得分:9)
这取决于你想做什么。您可以使用
选择其任何后代中包含“Find me”的所有<p/>
元素
//xhtml:p[contains(., 'Find me')]
这将返回重复项,因此您不指定节点类型,然后它也将返回<body/>
和<html/>
。
或许您希望任何包含子节点(不是后代)的节点包含“Find me”
//*[text()[contains(., 'Find me')]]
这个不会返回<html/>
或<body/>
。
我忘了提及.
表示节点的全文内容。 text()
用于检索[文本节点的节点集]。表达式contains(text(), 'Find me')
的问题在于contains()
仅适用于字符串,而不适用于节点集,因此会将text()
转换为第一个节点的值,这就是删除第一个{{1}使它工作。
答案 1 :(得分:1)
呃,嗯?但感谢@Jordy的快速回答。
首先,这是不需要的DOM-XML,因为我的脚本中的其他内容都是使用SimpleXML完成的。
其次,为什么要翻译成大写并搜索未找到的字符串'找到我'? “搜索'找到我'实际上会给出一个结果。
但是你指出了我正确的方向:
$nodes = $xml->xpath("//text()[contains(., 'Find me')]");
诀窍!
答案 2 :(得分:1)
我一直在寻找一种方法来查找具有确切值“Find Me”的节点是否存在,这似乎有效。
$node = $xml->xpath("//text()[.='Find Me']");
答案 3 :(得分:0)
$doc = new DOMDocument();
$doc->loadHTML($xhtml);
$xPath = new DOMXpath($doc);
$xPathQuery = "//text()[contains(translate(.,'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'), 'Find me')]";
$elements = $xPath->query($xPathQuery);
if($elements->length > 0){
foreach($elements as $element){
print "Found: " .$element->nodeValue."<br />";
}}