当前位置:Gxlcms > PHP教程 > html标签闭合检测与修复

html标签闭合检测与修复

时间:2021-07-01 10:21:17 帮助过:37人阅读

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

人气教程排行