当前位置:首页 > PHP教程 > php应用 > 列表

php实现html标签闭合检测与修复方法

发布:smiling 来源: PHP粉丝网  添加日期:2021-06-10 10:56:51 浏览: 评论:0 

这篇文章主要介绍了php实现html标签闭合检测与修复方法,可实现针对html标签中结束标签的检测与补全功能,非常具有实用价值,需要的朋友可以参考下

本文实例讲述了php实现html标签闭合检测与修复方法。分享给大家供大家参考。具体如下:

html标签闭合检测与修复,说的有点大 , 并没有考虑的很完整,没有使用正则表达式, 适用于html文件中只有开始标签没有结束标签, 是有结束标签没有开始标签的情况。标签闭合的位置需要根据需求调整。

  1. <?php 
  2. $str = ' 
  3. <div data="<li></li>"
  4.   <img src="http://www.phpfensi.com/123123.png"/> 
  5.   <div2> 
  6.     <a>content</a> 
  7.   </div2> 
  8.     <ul> 
  9.       <li> 
  10.       </li> 
  11.     </ul> 
  12.     <p> 
  13.     content full 
  14.     </p> 
  15.     this is content</test1> 
  16.     this is content</test2> 
  17.     <test4 data="liujinjing"> This is cont 
  18.     <li></li> 
  19.     <test3 data="liujinjing"> This is content 
  20. <div3> 
  21. </div3> 
  22. </div4> 
  23. </div> 
  24. </div> 
  25. <div6 style="width:90px; "> this is content'; 
  26. $str_len = strlen($str); 
  27. //记录起始标签 
  28. $pre_data = array(); 
  29. //记录起始标签位置 
  30. $pre_pos = array(); 
  31. $last_data = array(); 
  32. $error_data = array(); 
  33. $error_pos = array(); 
  34. $i = 0; 
  35. //标记为 < 开始 
  36. $start_flag = false; 
  37. while$i < $str_len ) { 
  38.   if($str[$i]=="<" && $str[$i+1]!='/' && $str[$i+1]!='!') { 
  39.     $i++; 
  40.     $_tmp_str = ''
  41.     //标记为 < 开始 
  42.     $start_flag = true; 
  43.     //标记空白 
  44.     $space_flag = false; 
  45.     while($str[$i]!=">" && $str[$i]!="'" && $str[$i]!='"' && $str[$i] !='/' && $i<$str_len){ 
  46.       if($str[$i]==' ') { 
  47.         $space_flag = true; 
  48.       } 
  49.       if(!$space_flag) { 
  50.         $_tmp_str .= $str[$i];   
  51.       } 
  52.       $i++; 
  53.     } 
  54.     $pre_data[] = $_tmp_str
  55.     $pre_pos[] = $i
  56.   } else if ($str[$i]=="<" && $str[$i+1]=='/') { 
  57.     $i += 2; 
  58.     $_tmp_str = ''
  59.     while($str[$i]!=">" && $i<$str_len){ 
  60.       $_tmp_str .= $str[$i]; 
  61.       $i++; 
  62.     } 
  63.     $last_data[] = $_tmp_str
  64.     //查看开始标签的上一个值 
  65.     if(count($pre_data)>0) { 
  66.       $last_pre_node = getLastNode($pre_data, 1); 
  67.       if($last_pre_node == $_tmp_str) { 
  68.         //配对上, 删除对应位置的值 
  69.         array_pop($pre_data); 
  70.         array_pop($pre_pos); 
  71.         array_pop($last_data); 
  72.       } else { 
  73.       //没有配对上, 有两种情况 
  74.         //情况一: 只有闭合标签, 没有开始标签 
  75.         //情况二:只有开始标签, 没有闭合标签 
  76.         array_pop($last_data); 
  77.         $error_data[] = $_tmp_str
  78.         $error_pos[] = $i
  79.       } 
  80.     } else { 
  81.         array_pop($last_data); 
  82.         $error_data[] = $_tmp_str
  83.         $error_pos[] = $i;       
  84.     } 
  85.   }else if ($str[$i]=="<" && $str[$i+1]=="!") { 
  86.     $i++; 
  87.     while($i<$str_len) { 
  88.       if($str[$i]=="-" && $str[$i+1]=="-" && $str[$i+2]==">") { 
  89.         $i++; 
  90.         break
  91.       } else { 
  92.         $i++; 
  93.       } 
  94.     } 
  95.     $i++; 
  96.   }else if($str[$i]=='/' && $str[$i+1]=='>') { 
  97.     //跳过自动单个闭合标签 
  98.     if($start_flag) { 
  99.       array_pop($pre_data); 
  100.       array_pop($pre_pos); 
  101.       $i+=2; 
  102.     } 
  103.   }else if($str[$i]=="/" && $str[$i+1]=="*"){ 
  104.     $i++; 
  105.     while($i<$str_len) { 
  106.       if($str[$i]=="*" && $str[$i+1]=="/") { 
  107.         $i++; 
  108.         break
  109.       } else { 
  110.         $i++; 
  111.     } 
  112.     $i++; 
  113.   } 
  114.   }else if($str[$i]=="'"){ 
  115.     $i++; 
  116.     while($str[$i]!="'" && $i<$str_len) { 
  117.       $i++; 
  118.     } 
  119.     $i++; 
  120.   } else if($str[$i]=='"'){ 
  121.     $i++; 
  122.     while($str[$i]!='"' && $i<$str_len ) { 
  123.       $i++; 
  124.     } 
  125.     $i++; 
  126.   } else { 
  127.     $i++; 
  128.   } 
  129. //确定起始标签的位置 
  130. function confirm_pre_pos($str$pre_pos){ 
  131.   $str_len = strlen($str); 
  132.   $j=$pre_pos
  133.   while($j < $str_len) { 
  134.     if($str[$j] == '"') { 
  135.       $j++; 
  136.       while ($j<$str_len) { 
  137.         if($str[$j]=='"') { 
  138.           $j++; 
  139.           break
  140.         } 
  141.         $j++; 
  142.       } 
  143.     } 
  144.     else if($str[$j] == "'") { 
  145.       $j++; 
  146.       while ($j<$str_len) { 
  147.         if($str[$j]=="'") { 
  148.           $j++; 
  149.           break
  150.         } 
  151.         $j++; 
  152.       } 
  153.     } 
  154.     else if($str[$j]==">") { 
  155.       $j++; 
  156.       while ($j<$str_len) { 
  157.         if($str[$j]=="<") { 
  158.           //退回到原有内容位置 
  159.           $j--; 
  160.           break
  161.         } 
  162.         $j++; 
  163.       } 
  164.       break
  165.     }  
  166.     else { 
  167.       $j++; 
  168.     } 
  169.   } 
  170.   return $j
  171. //确定起始标签的位置 
  172. function confirm_err_pos($str$err_pos){ 
  173.   $j=$err_pos
  174.   $j--; 
  175.   while($j > 0) { 
  176.     if($str[$j] == '"') { 
  177.       $j--; 
  178.       while ($j<$str_len) { 
  179.         if($str[$j]=='"') { 
  180.           $j--; 
  181.           break
  182.         } 
  183.         $j--; 
  184.       } 
  185.     } 
  186.     else if($str[$j] == "'") { 
  187.       $j--; 
  188.       while ($j<$str_len) { 
  189.         if($str[$j]=="'") { 
  190.           $j--; 
  191.           break
  192.         } 
  193.         $j--; 
  194.       } 
  195.     } 
  196.     else if($str[$j]==">") { 
  197.       $j++; 
  198.       break
  199.     }  
  200.     else { 
  201.       $j--; 
  202.     } 
  203.   } 
  204.   return $j
  205. //获取数组的倒数第num个值 
  206. function getLastNode(array $arr$num){ 
  207.   $len = count($arr); 
  208.   if($len > $num) { 
  209.     return $arr[$len-$num]; 
  210.   } else { 
  211.     return $arr[0]; 
  212.   } 
  213. //整理数据, 主要是向后看, 进一步进行检查 
  214. function sort_data(&$pre_data, &$pre_pos, &$error_data, &$error_pos){ 
  215.   $rem_key_array = array(); 
  216.   $rem_i_array = array(); 
  217.   //获取需要删除的值 
  218.   foreach($error_data as $key=>$value){ 
  219.     $count = count($pre_data); 
  220.     for($i=($count-1) ; $i>=0; $i--) { 
  221.       if($pre_data[$i] == $value && !in_array($i$rem_i_array)) { 
  222.         $rem_key_array[] = $key
  223.         $rem_i_array[] = $i
  224.         break
  225.       } 
  226.     } 
  227.   } 
  228.   //删除起始标签相应的值 
  229.   foreach($rem_key_array as $_item) { 
  230.     unset($error_pos[$_item]); 
  231.     unset($error_data[$_item]); 
  232.   } 
  233.   //删除结束标签相应的值 
  234.   foreach($rem_i_array as $_item) { 
  235.     unset($pre_data[$_item]); 
  236.     unset($pre_pos[$_item]); 
  237.   } 
  238. //整理数据, 闭合标签 
  239. function modify_data($str$pre_data$pre_pos$error_data$error_pos){ 
  240.   $move_log = array(); 
  241.   //只有闭合标签的数据 
  242.   foreach ($error_data as $key => $value) { 
  243.     // code... 
  244.     $_tmp_move_count = 0; 
  245.     foreach ($move_log as $pos_key => $move_value) { 
  246.       // code... 
  247.       if($error_pos[$key]>=$pos_key) { 
  248.         $_tmp_move_count += $move_value
  249.       } 
  250.     } 
  251.     $data = insert_data($str$value$error_pos[$key]+$_tmp_move_count, false); 
  252.     $str = $data['str']; 
  253.     $move_log[$data['pos']] = $data['move_count']; 
  254.   } 
  255.   //只有起始标签的数据 
  256.   foreach ($pre_data as $key => $value) { 
  257.     // code... 
  258.     $_tmp_move_count = 0; 
  259.     foreach ($move_log as $pos_key => $move_value) { 
  260.       // code... 
  261.       if($pre_pos[$key]>=$pos_key) { 
  262.         $_tmp_move_count += $move_value
  263.       } 
  264.     } 
  265.     $data = insert_data($str$value$pre_pos[$key]+$_tmp_move_count, true); 
  266.     $str = $data['str']; 
  267.     $move_log[$data['pos']] = $data['move_count']; 
  268.   } 
  269.   return $str
  270. //插入数据, $type 表示插入数据的方式 
  271. function insert_data($str$insert_data$pos$type) { 
  272.   $len = strlen($str); 
  273.   //起始标签类型 
  274.   if($type==true) { 
  275.     $move_count = strlen($insert_data)+3; 
  276.     $pos = confirm_pre_pos($str$pos); 
  277.     $pre_str = substr($str, 0, $pos); 
  278.     $end_str = substr($str$pos); 
  279.     $mid_str = "</" . $insert_data . ">"
  280.   //闭合标签类型 
  281.   } else { 
  282.     $pos = confirm_err_pos($str$pos); 
  283.     $move_count = strlen($insert_data) + 2; 
  284.     $pre_str = substr($str, 0, $pos); 
  285.     $end_str = substr($str$pos); 
  286.     $mid_str = "<" . $insert_data . ">"
  287.   } 
  288.   $str = $pre_str.$mid_str.$end_str
  289.   return array('str'=>$str'pos'=>$pos'move_count'=>$move_count); 
  290. sort_data($pre_data$pre_pos$error_data$error_pos); 
  291. $new_str = modify_data($str$pre_data$pre_pos$error_data$error_pos); 
  292. echo $new_str
  293. // print_r($pre_data); 
  294. // print_r($pre_pos); 
  295. // print_r($error_data); 
  296. // print_r($error_pos); 
  297. // echo strlen($str); 
  298. // foreach($pre_pos as $value){ 
  299. //   $value = confirm_pre_pos($str, $value); 
  300. //   for($i=$value-5; $i<=$value; $i++) { 
  301. //     echo $str[$i]; 
  302. //   } 
  303. //   echo "\n"; 
  304. // } 
  305. // foreach($error_pos as $value){ 
  306. //   for($i=$value-5; $i<=$value; $i++) { 
  307. //     echo $str[$i]; 
  308. //   } 
  309. //   echo "\n"; 
  310. // } 
  311. ?> 

希望本文所述对大家的php程序设计有所帮助。

Tags: php标签闭合 html标签闭合

分享到: