有些时候我们需要匹配div对应的结束标记,既不是最先出现的</div>标记,也不是最后出现的</div>标记,例如有一段html:
我们想获取其中红色方框里的内容,正确的结束标记应该是第19行的</div>,但是如果用正则或其strpos找到的位置,很有可能是第13行或者第23行的</div>,都不是我们想要的结果。
这里可以用到堆栈的思想,首先第一个<div开始时,将该位置压入堆栈,然后继续向后读取,当遇到<div时就入栈,遇到</div>时就出栈,知道数组为空时,也就找到了对应匹配的</div>的位置,也就是第19行。
实现代码如下:
<?php function GetHtmlArea($sptag, $areaRule, $html) { $areaRules = explode($sptag,$areaRule); if($html=='' || $areaRules[0]=='') { return ''; } $posstart = @strpos($html,$areaRules[0]); if($posstart===FALSE) { return ''; } $html_after = substr($html,$posstart); $count = substr_count($html_after,$areaRules[1]); if($count>1 && $areaRules[1]=='</div>'){ $html_after = substr($html,$posstart+strlen($areaRules[0])); $position = 0; $arr[0] =$posstart+strlen($areaRules[0]); for($i=0;$i<strlen($html_after);$i++){ if(substr($html_after,$i,4)=='<div'){ array_push($arr,$i); continue; } if(substr($html_after,$i,6)=='</div>'){ array_pop($arr); if(empty($arr)){ $position = $i; break; } continue; } } $html = substr($html,$posstart,$position+strlen($areaRules[0])+6); return $html; }else{ $posstart = $posstart + strlen($areaRules[0]); $posend = @strpos($html,$areaRules[1],$posstart); if($posend > $posstart && $posend!==FALSE) { return substr($html,$posstart,$posend-$posstart); } else { return ''; } } } $str = ' <html> <head> <title> New Document </title> <meta charset="utf-8" /> </head> <body> <div class="box"> 这里有一些内容 <div class="box_1"> 这里又有一些内容 <div class="box_1_1">这里还有一些内容</div> </div> <div class="box_2"> 这里又有一些内容 <div class="box_2_1">这里还有一些内容</div> </div> </div> <div class="box2"> 这里又有一些内容 <div class="box_3_1">这里还有一些内容</div> </div> </body> </html>'; $areaRule = '<div class="box">[内容]</div>'; $result = GetHtmlArea('[内容]',$areaRule,$str); var_dump($result);die;