Welcome 微信登录

首页 / 网页编程 / PHP / php实现html标签闭合检测与修复方法

本文实例讲述了php实现html标签闭合检测与修复方法。分享给大家供大家参考。具体如下:
html标签闭合检测与修复,说的有点大 , 并没有考虑的很完整,没有使用正则表达式, 适用于html文件中只有开始标签没有结束标签, 是有结束标签没有开始标签的情况。标签闭合的位置需要根据需求调整
<?php$str = "<div data="<li></li>"><img src="http://www.baidu.com/123123.png"/><div2><a>content</a></div2><ul><li></li></ul><p>content full</p>this is content</test1>this is content</test2><test4 data="liujinjing"> This is cont<li></li><test3 data="liujinjing"> This is content<div3></div3></div4></div></div><div6 style="width:90px; "> this is content";$str_len = strlen($str);//记录起始标签$pre_data = array();//记录起始标签位置$pre_pos = array();$last_data = array();$error_data = array();$error_pos = array();$i = 0;//标记为 < 开始$start_flag = false;while( $i < $str_len ) {if($str[$i]=="<" && $str[$i+1]!="/" && $str[$i+1]!="!") {$i++;$_tmp_str = "";//标记为 < 开始$start_flag = true;//标记空白$space_flag = false;while($str[$i]!=">" && $str[$i]!=""" && $str[$i]!=""" && $str[$i] !="/" && $i<$str_len){if($str[$i]==" ") {$space_flag = true;}if(!$space_flag) {$_tmp_str .= $str[$i];}$i++;}$pre_data[] = $_tmp_str;$pre_pos[] = $i;} else if ($str[$i]=="<" && $str[$i+1]=="/") {$i += 2;$_tmp_str = "";while($str[$i]!=">" && $i<$str_len){$_tmp_str .= $str[$i];$i++;}$last_data[] = $_tmp_str;//查看开始标签的上一个值if(count($pre_data)>0) {$last_pre_node = getLastNode($pre_data, 1);if($last_pre_node == $_tmp_str) {//配对上, 删除对应位置的值array_pop($pre_data);array_pop($pre_pos);array_pop($last_data);} else {//没有配对上, 有两种情况//情况一: 只有闭合标签, 没有开始标签//情况二:只有开始标签, 没有闭合标签array_pop($last_data);$error_data[] = $_tmp_str;$error_pos[] = $i;}} else {array_pop($last_data);$error_data[] = $_tmp_str;$error_pos[] = $i;}}else if ($str[$i]=="<" && $str[$i+1]=="!") {$i++;while($i<$str_len) {if($str[$i]=="-" && $str[$i+1]=="-" && $str[$i+2]==">") {$i++;break;} else {$i++;}}$i++;}else if($str[$i]=="/" && $str[$i+1]==">") {//跳过自动单个闭合标签if($start_flag) {array_pop($pre_data);array_pop($pre_pos);$i+=2;}}else if($str[$i]=="/" && $str[$i+1]=="*"){$i++;while($i<$str_len) {if($str[$i]=="*" && $str[$i+1]=="/") {$i++;break;} else {$i++;}$i++;}}else if($str[$i]=="""){$i++;while($str[$i]!=""" && $i<$str_len) {$i++;}$i++;} else if($str[$i]=="""){$i++;while($str[$i]!=""" && $i<$str_len ) {$i++;}$i++;} else {$i++;}}//确定起始标签的位置function confirm_pre_pos($str, $pre_pos){$str_len = strlen($str);$j=$pre_pos;while($j < $str_len) {if($str[$j] == """) {$j++;while ($j<$str_len) {if($str[$j]==""") {$j++;break;}$j++;}}else if($str[$j] == """) {$j++;while ($j<$str_len) {if($str[$j]==""") {$j++;break;}$j++;}}else if($str[$j]==">") {$j++;while ($j<$str_len) {if($str[$j]=="<") {//退回到原有内容位置$j--;break;}$j++;}break;} else {$j++;}}return $j;}//确定起始标签的位置function confirm_err_pos($str, $err_pos){$j=$err_pos;$j--;while($j > 0) {if($str[$j] == """) {$j--;while ($j<$str_len) {if($str[$j]==""") {$j--;break;}$j--;}}else if($str[$j] == """) {$j--;while ($j<$str_len) {if($str[$j]==""") {$j--;break;}$j--;}}else if($str[$j]==">") {$j++;break;} else {$j--;}}return $j;}//获取数组的倒数第num个值function getLastNode(array $arr, $num){$len = count($arr);if($len > $num) {return $arr[$len-$num];} else {return $arr[0];}}//整理数据, 主要是向后看, 进一步进行检查function sort_data(&$pre_data, &$pre_pos, &$error_data, &$error_pos){$rem_key_array = array();$rem_i_array = array();//获取需要删除的值foreach($error_data as $key=>$value){$count = count($pre_data);for($i=($count-1) ; $i>=0; $i--) {if($pre_data[$i] == $value && !in_array($i, $rem_i_array)) {$rem_key_array[] = $key;$rem_i_array[] = $i;break;}}}//删除起始标签相应的值foreach($rem_key_array as $_item) {unset($error_pos[$_item]);unset($error_data[$_item]);}//删除结束标签相应的值foreach($rem_i_array as $_item) {unset($pre_data[$_item]);unset($pre_pos[$_item]);}}//整理数据, 闭合标签function modify_data($str, $pre_data, $pre_pos, $error_data, $error_pos){$move_log = array();//只有闭合标签的数据foreach ($error_data as $key => $value) {// code...$_tmp_move_count = 0;foreach ($move_log as $pos_key => $move_value) {// code...if($error_pos[$key]>=$pos_key) {$_tmp_move_count += $move_value;}}$data = insert_data($str, $value, $error_pos[$key]+$_tmp_move_count, false);$str = $data["str"];$move_log[$data["pos"]] = $data["move_count"];}//只有起始标签的数据foreach ($pre_data as $key => $value) {// code...$_tmp_move_count = 0;foreach ($move_log as $pos_key => $move_value) {// code...if($pre_pos[$key]>=$pos_key) {$_tmp_move_count += $move_value;}}$data = insert_data($str, $value, $pre_pos[$key]+$_tmp_move_count, true);$str = $data["str"];$move_log[$data["pos"]] = $data["move_count"];}return $str;}//插入数据, $type 表示插入数据的方式function insert_data($str, $insert_data, $pos, $type) {$len = strlen($str);//起始标签类型if($type==true) {$move_count = strlen($insert_data)+3;$pos = confirm_pre_pos($str, $pos);$pre_str = substr($str, 0, $pos);$end_str = substr($str, $pos);$mid_str = "</" . $insert_data . ">";//闭合标签类型} else {$pos = confirm_err_pos($str, $pos);$move_count = strlen($insert_data) + 2;$pre_str = substr($str, 0, $pos);$end_str = substr($str, $pos);$mid_str = "<" . $insert_data . ">";}$str = $pre_str.$mid_str.$end_str;return array("str"=>$str, "pos"=>$pos, "move_count"=>$move_count);}sort_data($pre_data, $pre_pos, $error_data, $error_pos);$new_str = modify_data($str, $pre_data, $pre_pos, $error_data, $error_pos);echo $new_str;// print_r($pre_data);// print_r($pre_pos);// print_r($error_data);// print_r($error_pos);// echo strlen($str);// foreach($pre_pos as $value){// $value = confirm_pre_pos($str, $value);// for($i=$value-5; $i<=$value; $i++) {// echo $str[$i];// }// echo "
";// }// foreach($error_pos as $value){// for($i=$value-5; $i<=$value; $i++) {// echo $str[$i];// }// echo "
";// }?>
希望本文所述对大家的php程序设计有所帮助。