当前位置:首页 > 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. //确定起始标签的位置 
  131. function confirm_pre_pos($str, $pre_pos){ 
  132.   $str_len = strlen($str); 
  133.   $j=$pre_pos; 
  134.   while($j < $str_len) { 
  135.     if($str[$j] == '"') { 
  136.       $j++; 
  137.       while ($j<$str_len) { 
  138.         if($str[$j]=='"') { 
  139.           $j++; 
  140.           break; 
  141.         } 
  142.         $j++; 
  143.       } 
  144.     } 
  145.     else if($str[$j] == "'") { 
  146.       $j++; 
  147.       while ($j<$str_len) { 
  148.         if($str[$j]=="'") { 
  149.           $j++; 
  150.           break; 
  151.         } 
  152.         $j++; 
  153.       } 
  154.     } 
  155.     else if($str[$j]==">") { 
  156.       $j++; 
  157.       while ($j<$str_len) { 
  158.         if($str[$j]=="<") { 
  159.           //退回到原有内容位置 
  160.           $j--; 
  161.           break; 
  162.         } 
  163.         $j++; 
  164.       } 
  165.       break; 
  166.     }  
  167.     else { 
  168.       $j++; 
  169.     } 
  170.   } 
  171.   return $j; 
  172. } 
  173. //确定起始标签的位置 
  174. function confirm_err_pos($str, $err_pos){ 
  175.   $j=$err_pos; 
  176.   $j--; 
  177.   while($j > 0) { 
  178.     if($str[$j] == '"') { 
  179.       $j--; 
  180.       while ($j<$str_len) { 
  181.         if($str[$j]=='"') { 
  182.           $j--; 
  183.           break; 
  184.         } 
  185.         $j--; 
  186.       } 
  187.     } 
  188.     else if($str[$j] == "'") { 
  189.       $j--; 
  190.       while ($j<$str_len) { 
  191.         if($str[$j]=="'") { 
  192.           $j--; 
  193.           break; 
  194.         } 
  195.         $j--; 
  196.       } 
  197.     } 
  198.     else if($str[$j]==">") { 
  199.       $j++; 
  200.       break; 
  201.     }  
  202.     else { 
  203.       $j--; 
  204.     } 
  205.   } 
  206.   return $j; 
  207. } 
  208. //获取数组的倒数第num个值 
  209. function getLastNode(array $arr, $num){ 
  210.   $len = count($arr); 
  211.   if($len > $num) { 
  212.     return $arr[$len-$num]; 
  213.   } else { 
  214.     return $arr[0]; 
  215.   } 
  216. } 
  217. //整理数据, 主要是向后看, 进一步进行检查 
  218. function sort_data(&$pre_data, &$pre_pos, &$error_data, &$error_pos){ 
  219.   $rem_key_array = array(); 
  220.   $rem_i_array = array(); 
  221.   //获取需要删除的值 
  222.   foreach($error_data as $key=>$value){ 
  223.     $count = count($pre_data); 
  224.     for($i=($count-1) ; $i>=0; $i--) { 
  225.       if($pre_data[$i] == $value && !in_array($i, $rem_i_array)) { 
  226.         $rem_key_array[] = $key; 
  227.         $rem_i_array[] = $i; 
  228.         break; 
  229.       } 
  230.     } 
  231.   } 
  232.   //删除起始标签相应的值 
  233.   foreach($rem_key_array as $_item) { 
  234.     unset($error_pos[$_item]); 
  235.     unset($error_data[$_item]); 
  236.   } 
  237.   //删除结束标签相应的值 
  238.   foreach($rem_i_array as $_item) { 
  239.     unset($pre_data[$_item]); 
  240.     unset($pre_pos[$_item]); 
  241.   } 
  242. } 
  243. //整理数据, 闭合标签 
  244. function modify_data($str, $pre_data, $pre_pos, $error_data, $error_pos){ 
  245.   $move_log = array(); 
  246.   //只有闭合标签的数据 
  247.   foreach ($error_data as $key => $value) { 
  248.     // code... 
  249.     $_tmp_move_count = 0; 
  250.     foreach ($move_log as $pos_key => $move_value) { 
  251.       // code... 
  252.       if($error_pos[$key]>=$pos_key) { 
  253.         $_tmp_move_count += $move_value; 
  254.       } 
  255.     } 
  256.     $data = insert_data($str, $value, $error_pos[$key]+$_tmp_move_count, false); 
  257.     $str = $data['str']; 
  258.     $move_log[$data['pos']] = $data['move_count']; 
  259.   } 
  260.   //只有起始标签的数据 
  261.   foreach ($pre_data as $key => $value) { 
  262.     // code... 
  263.     $_tmp_move_count = 0; 
  264.     foreach ($move_log as $pos_key => $move_value) { 
  265.       // code... 
  266.       if($pre_pos[$key]>=$pos_key) { 
  267.         $_tmp_move_count += $move_value; 
  268.       } 
  269.     } 
  270.     $data = insert_data($str, $value, $pre_pos[$key]+$_tmp_move_count, true); 
  271.     $str = $data['str']; 
  272.     $move_log[$data['pos']] = $data['move_count']; 
  273.   } 
  274.   return $str; 
  275. } 
  276. //插入数据, $type 表示插入数据的方式 
  277. function insert_data($str, $insert_data, $pos, $type) { 
  278.   $len = strlen($str); 
  279.   //起始标签类型 
  280.   if($type==true) { 
  281.     $move_count = strlen($insert_data)+3; 
  282.     $pos = confirm_pre_pos($str, $pos); 
  283.     $pre_str = substr($str, 0, $pos); 
  284.     $end_str = substr($str, $pos); 
  285.     $mid_str = "</" . $insert_data . ">"; 
  286.   //闭合标签类型 
  287.   } else { 
  288.     $pos = confirm_err_pos($str, $pos); 
  289.     $move_count = strlen($insert_data) + 2; 
  290.     $pre_str = substr($str, 0, $pos); 
  291.     $end_str = substr($str, $pos); 
  292.     $mid_str = "<" . $insert_data . ">"; 
  293.   } 
  294.   $str = $pre_str.$mid_str.$end_str; 
  295.   return array('str'=>$str, 'pos'=>$pos, 'move_count'=>$move_count); 
  296. } 
  297. sort_data($pre_data, $pre_pos, $error_data, $error_pos); 
  298. $new_str = modify_data($str, $pre_data, $pre_pos, $error_data, $error_pos); 
  299. echo $new_str; 
  300. // print_r($pre_data); 
  301. // print_r($pre_pos); 
  302. // print_r($error_data); 
  303. // print_r($error_pos); 
  304. // echo strlen($str); 
  305. // foreach($pre_pos as $value){ 
  306. //   $value = confirm_pre_pos($str, $value); 
  307. //   for($i=$value-5; $i<=$value; $i++) { 
  308. //     echo $str[$i]; 
  309. //   } 
  310. //   echo "\n"; 
  311. // } 
  312. // foreach($error_pos as $value){ 
  313. //   for($i=$value-5; $i<=$value; $i++) { 
  314. //     echo $str[$i]; 
  315. //   } 
  316. //   echo "\n"; 
  317. // } 
  318. ?> 

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

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

分享到: