有些时候我们需要匹配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;
