我无法找到解决这个问题的方法
<div>
<p id="p1"> Price is <span>$ 25</span></p>
<p id='p2'> But this price is $ <span id="s1">50,23</span> </p>
<p id='p3'> This one : $ 14540.12 dollar</p>
</div>
我要做的是找到一个价格合理的元素,这是它的最短路径。 这就是我所熟悉的。
$elements = $dom->getElementsByTagName('*');
foreach($elements as $child)
{
if (preg_match("/.$regex./",$child->nodeValue)){
echo $child->getNodePath(). "<br />";
}
}
这导致
/html
/html/body
/html/body/div
/html/body/div/p[1]
/html/body/div/p[1]/span
/html/body/div/p[2]
/html/body/div/p[2]/span
/html/body/div/p[3]
这些是我想要的元素的路径,所以在这个测试HTML中没问题。但在真正的网页中,这些路径变得非常长并且容易出错。 我想要做的是找到具有ID属性的最接近的元素并参考它。
因此,一旦找到与$ regex匹配的元素,我需要向上移动DOM并找到第一个带有ID属性的元素并从中创建新的较短路径。 在上面的HTML示例中,有3个价格与$ regex相匹配。价格如下:
//p[@id="p1"]/span
//p[@id="s1"]
//p[@id="p3"]
这就是我希望从我的功能中返回的内容。我还需要摆脱存在的所有其他路径,因为它们不包含$ regex
对此有何帮助?
答案 0 :(得分:0)
您可以使用XPath跟随祖先路径到包含@id
属性的第一个节点,然后关闭其路径。没有清理代码,但是这样的话:
// snip
$xpath = new DomXPath($doc);
foreach($elements as $child)
{
$textValue = '';
foreach ($xpath->query('text()', $child) as $text)
$textValue .= $text->nodeValue;
if (preg_match("/.$regex./", $textValue)) {
$path = $child->getNodePath();
$id = $xpath->query('ancestor-or-self::*[@id][1]', $child)->item(0);
$idpath = '';
if ($id) {
$idpath = $id->getNodePath();
$path = '//'.$id->nodeName.'[@id="'.$id->attributes->getNamedItem('id')->value.'"]'.substr($path, strlen($idpath));
}
echo $path."\n";
}
}
打印类似
的内容/html
/html/body
/html/body/div
//p[@id="p1"]
//p[@id="p1"]/span
//p[@id="p2"]
//span[@id="s1"]
//p[@id="p3"]