Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/289.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 向后遍历DOM查找id_Php_Dom_Xpath - Fatal编程技术网

Php 向后遍历DOM查找id

Php 向后遍历DOM查找id,php,dom,xpath,Php,Dom,Xpath,我不知道怎么解决这个问题 <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>
  <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>
这些是我想要的元素的路径,所以在这个测试HTML中没有问题。但在真实的网页中,这些路径很长,并且容易出错。 我想做的是找到具有ID属性的最近元素并引用它

因此,一旦找到与$regex匹配的and元素,我需要遍历DOM,找到具有and ID属性的第一个元素,并从中创建新的较短路径。 在上面的HTML示例中,有3个价格与$regex匹配。价格如下:

//p[@id=“p1”]/span
//p[@id=“s1”]
//p[@id=“p3”]
这就是我希望从函数返回的结果。这意味着我还需要去掉所有其他存在的路径,因为它们不包含$regex


有什么帮助吗?

您可以使用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/正文
/html/body/div
//p[@id=“p1”]
//p[@id=“p1”]/span
//p[@id=“p2”]
//span[@id=“s1”]
//p[@id=“p3”]

我应该改用SimpleXML吗?因此,这将是某种预处理分析,以准备将要应用的实际XSLT?有趣!伟大的詹斯!这是有效的,它确实给了我如上所述的输出。现在我想删除不必要的路径。在本例中,我只需要//p[@id=“p1”]/span、//span[@id=“s1”]和//p[@id=“p3”]。我怎样才能做到这一点?什么是“不必要的路径”?无论如何,这可能更适合作为一个新问题。不要把这当作一个新问题。我正在寻找包含$regex的元素的最短路径。正如您在上面的答案中所看到的,这些路径是//p[@id=“p1”]/span//span[@id=“s1”]//p[@id=“p3”]所以我不需要/html、/html/body等。也不需要//p[@id=“p1”]因为正则表达式是在下面的span中找到的(参见上面的输出),所以在我的示例中,我只需要3行输出,剩下的是不必要的,我仍然不知道如何过滤路径,我不认为你在你的问题中描述了这一点。如果我遗漏了什么,请强调我遗漏了什么。我没有用你的正则表达式改变任何东西,那一定是从一开始就被破坏了。Jens谢谢,我已经重写了我的问题,我希望这能让事情变得更清楚。感谢你的帮助!
/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]
// 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";
   }
}