【问题标题】:How To get DiVs Level?如何获得 DiVs 级别?
【发布时间】:2021-06-24 14:35:53
【问题描述】:
$html ='<html>
<head>
    <title></title>
</head>
<body>
    <div class="">
        <div class="">
           <p><strong><span style="color:#FF0000"> Content1 </span></strong></p>
           <p style="text-align:center"> Content2 <img src="https://example.com/bla1.jpg"/></p>
        </div>
       
        <h2> Header </h2>
        <div class=""><p><strong> Content3 </strong></p> </div>

    </div>

    <div class=""> Content4 </div>
    <div class="">
                   <p> Content5 </p>  
                   <p> Content6 </p> 
                   <span> blah.. </span>
    </div>
</body></html>';

我需要这样一个数组:

这表示每个DIV(包括P)是否有子DIV或父DIV?

【问题讨论】:

  • 为什么要专门使用getElementsByTagName?如果你使用XPath,这个任务会简单很多
  • 我不知道 xpath 可以帮忙举个例子吗?

标签: php dom domdocument getelementsbytagname


【解决方案1】:

除非您承诺仅将 getElementsByTagName 与父/子选择器结合使用,否则您可能会发现一个简单的 XPath 查询是查找位于 div 元素内的 p 元素的最简单方法。

$html ='<html>
<head>
    <title></title>
</head>
<body>
    <div class="">
        <div class="">
           <p><strong><span style="color:#FF0000"> Content1 </span></strong></p>
           <p style="text-align:center"> Content2 <img src="https://example.com/bla1.jpg"/></p>
        </div>
       
        <h2> Header </h2>
        <div class=""><p><strong> Content3 </strong></p> </div>

    </div>

    <div class=""> Content4 </div>
    <div class="">
                   <p> Content5 </p>  
                   <p> Content6 </p> 
                   <span> blah.. </span>
    </div>
</body></html>';


$tmp=array();


$dom=new DOMDocument;
$dom->loadHTML( $html );

$xp=new DOMXPath( $dom );
$col=$xp->query('//div/p');

if( $col && $col->length > 0 ){
    foreach( $col as $node )$tmp[]=$node->textContent;
}

printf('<textarea cols=100 rows=10>%s</textarea>',print_r( $tmp, true ) );

产量:

更新:

您希望存储节点中包含的完整 HTML,而不是存储 nodeValue / textContent,以便为此您 clone 节点(及其内容)并将其保存到输出数组。

$tmp=array();


$dom=new DOMDocument;
$dom->loadHTML( $html );

$xp=new DOMXPath( $dom );
$col=$xp->query('//div/p');

if( $col && $col->length > 0 ){
    foreach( $col as $node ){
        $clone=$node->cloneNode( true ); //clone node with ALL children
        $tmp[]=$dom->saveHTML( $clone ); // save the HTML within
    }
}

printf('<textarea cols=100 rows=10>%s</textarea>',print_r( $tmp, true ) );

【讨论】:

  • 非常感谢。但我需要上述格式的输出。用原来的html结构
  • OK - 做了一个我认为满足您要求的更改
  • 再次感谢您。这段代码非常接近我的目标。但我需要在单独的部门(divs)中获取段落(P 标签)。在我的示例中,有三个包含 'P tags' 的 'div'(嵌套和非嵌套)。因此,输出必须包含数组的三个单元格。如上所述。
【解决方案2】:

你的尝试是一个不错的尝试,但如果div 是当前p 节点的父节点,我宁愿获取所有p 标记,然后爬上DOM 节点层次结构。这样,您将只收集那些以 div 为父节点的 p 节点,而不是其他节点。换句话说,它就像 CSS 选择器div &gt; p

$ps = array();
$doc = new DomDocument('1.0', 'UTF-8');
$doc->loadHTML(mb_convert_encoding($HTML, 'HTML-ENTITIES', 'UTF-8'));

foreach($doc->getElementsByTagName('p') as $p){
   $curr_node = $p->parentNode;
   while(property_exists($curr_node,'tagName')){
      if($curr_node->tagName == 'div'){
        $ps[] = $p;
        break;
      }
      $curr_node = $curr_node->parentNode;
      if($curr_node === null) break;
   }
}

print_r($ps);

更新 #1:

要获得每个divps,您可以递归遍历每个div 的所有子节点并收集所有ps 并将其添加到结果中,如下所示:

function getPs($node,&$result){
    foreach ($node->childNodes as $c_node) {
        if(property_exists($c_node, 'tagName') && $c_node->tagName == 'p'){
            $result[] = $c_node;
        }
        getPs($c_node,$result);
    }
}

$ps = [];

foreach($doc->getElementsByTagName('div') as $div){
   $child_ps = [];
   getPs($div,$child_ps);
   if(count($child_ps) > 0) $ps[] = $child_ps;
}

echo "<pre>";
print_r($ps);

更新 #2:

要获取 p 节点的 HTML 字符串表示,请更改

$result[] = $c_node;

$result[] = $c_node->ownerDocument->saveXML( $c_node );

【讨论】:

  • 非常感谢。但我需要上述格式的输出。用原来的html结构
  • @yaradan 您只需使用关联数组按父 div 对数据进行分组或使用递归遍历 div 的所有子节点
  • @yaradan 更新了我的答案。您可以使用-&gt;textNode 我相信可以获取其中的 HTML 部分。
  • 非常感谢 这段代码很好用。如何在输出中使用 saveHTML?也就是说,我有“整个元素”而不是“内容”。也就是说,应该打印“

    Content1

    ”而不是“Content1”
  • @yaradan 有什么问题吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-01-30
  • 1970-01-01
  • 2019-05-18
  • 1970-01-01
  • 2021-12-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多