Maison > développement back-end > tutoriel php > 修复未正常关闭的HTML标签(支持嵌套和就近闭合)的代码

修复未正常关闭的HTML标签(支持嵌套和就近闭合)的代码

WBOY
Libérer: 2016-07-25 09:05:16
original
1172 Les gens l'ont consulté
  1. /**

  2. * fixHtmlTag
  3. *
  4. * html标签修复函数,此函数可以修复未正确闭合的 HTML 标签
  5. *
  6. * 由于不确定性因素太多,暂时提供两种模式“嵌套闭合模式”和
  7. * “就近闭合模式”,应该够用了。
  8. *
  9. * 这两种模式是我为了解释清楚此函数的实现而创造的两个名词,
  10. * 只需明白什么意思就行。
  11. * 1,嵌套闭合模式,NEST,为默认的闭合方式。即 "
    你好"
  12. * 这样的 html 代码会被修改为 "
    你好
    "
  13. * 2,就近闭合模式,CLOSE,这种模式会将形如 "

    你好

    为什么没有

  14. * 闭合呢" 的代码修改为 "

    你好

    为什么没有闭合呢

    "
  15. *
  16. * 在嵌套闭合模式(默认,无需特殊传参)下,可以传入需要就近闭合的
  17. * 标签名,通过这种方式将类似 "

    你好

    我也好" 转换为

  18. * "

    你好

    我也好

    "的形式。
  19. * 传参时索引需要按照如下方式写,不需要修改的设置可以省略
  20. *
  21. * $param = array(
  22. * 'html' => '', //必填
  23. * 'options' => array(
  24. * 'tagArray' => array();
  25. * 'type' => 'NEST',
  26. * 'length' => null,
  27. * 'lowerTag' => TRUE,
  28. * 'XHtmlFix' => TRUE,
  29. * )
  30. * );
  31. * fixHtmlTag($param);
  32. *
  33. * 上面索引对应的值含义如下
  34. * string $html 需要修改的 html 代码
  35. * array $tagArray 当为嵌套模式时,需要就近闭合的标签数组
  36. * string $type 模式名,目前支持 NEST 和 CLOSE 两种模式,如果设置为 CLOSE,将会忽略参数 $tagArray 的设置,而全部就近闭合所有标签
  37. * ini $length 如果希望截断一定长度,可以在此赋值,此长度指的是字符串长度
  38. * bool $lowerTag 是否将代码中的标签全部转换为小写,默认为 TRUE
  39. * bool $XHtmlFix 是否处理不符合 XHTML 规范的标签,即将
    转换为
  40. *
  41. * @author IT不倒翁
  42. * @version 0.2
  43. * @link http://bbs.it-home.org IT不倒翁
  44. * @link http://enenba.com/?post=19 某某
  45. * @param array $param 数组参数,需要赋予特定的索引
  46. * @return string $result 经过处理后的 html 代码
  47. * @since 2012-04-14
  48. */
  49. function fixHtmlTag($param = array()) {
  50. //参数的默认值
  51. $html = '';
  52. $tagArray = array();
  53. $type = 'NEST';
  54. $length = null;
  55. $lowerTag = TRUE;
  56. $XHtmlFix = TRUE;
  57. //首先获取一维数组,即 $html 和 $options (如果提供了参数)

  58. extract($param);
  59. //如果存在 options,提取相关变量

  60. if (isset($options)) {
  61. extract($options);
  62. }
  63. $result = ''; //最终要返回的 html 代码

  64. $tagStack = array(); //标签栈,用 array_push() 和 array_pop() 模拟实现
  65. $contents = array(); //用来存放 html 标签
  66. $len = 0; //字符串的初始长度
  67. //设置闭合标记 $isClosed,默认为 TRUE, 如果需要就近闭合,成功匹配开始标签后其值为 false,成功闭合后为 true

  68. $isClosed = true;
  69. //将要处理的标签全部转为小写

  70. $tagArray = array_map('strtolower', $tagArray);
  71. //“合法”的单闭合标签

  72. $singleTagArray = array(
  73. ''''
    '
    ''修复未正常关闭的HTML标签(支持嵌套和就近闭合)的代码 );
  74. //校验匹配模式 $type,默认为 NEST 模式

  75. $type = strtoupper($type);
  76. if (!in_array($type, array('NEST', 'CLOSE'))) {
  77. $type = 'NEST';
  78. }
  79. //以一对 为分隔符,将原 html 标签和标签内的字符串放到数组中

  80. $contents = preg_split("/(]+?>)/si", $html, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
  81. foreach ($contents as $tag) {

  82. if ('' == trim($tag)) {
  83. $result .= $tag;
  84. continue;
  85. }
  86. //匹配标准的单闭合标签,如

  87. if (preg_match("/]*?\/>/si", $tag)) {
  88. $result .= $tag;
  89. continue;
  90. }
  91. //匹配开始标签,如果是单标签则出栈

  92. else if (preg_match("/]*?>/si", $tag, $match)) {
  93. //如果上一个标签没有闭合,并且上一个标签属于就近闭合类型
  94. //则闭合之,上一个标签出栈
  95. //如果标签未闭合

  96. if (false === $isClosed) {
  97. //就近闭合模式,直接就近闭合所有的标签
  98. if ('CLOSE' == $type) {
  99. $result .= '' . end($tagStack) . '>';
  100. array_pop($tagStack);
  101. }
  102. //默认的嵌套模式,就近闭合参数提供的标签
  103. else {
  104. if (in_array(end($tagStack), $tagArray)) {
  105. $result .= '' . end($tagStack) . '>';
  106. array_pop($tagStack);
  107. }
  108. }
  109. }
  110. //如果参数 $lowerTag 为 TRUE 则将标签名转为小写

  111. $matchLower = $lowerTag == TRUE ? strtolower($match[1]) : $match[1];
  112. $tag = str_replace('//开始新的标签组合

  113. $result .= $tag;
  114. array_push($tagStack, $matchLower);
  115. //如果属于约定的的单标签,则闭合之并出栈

  116. foreach ($singleTagArray as $singleTag) {
  117. if (stripos($tag, $singleTag) !== false) {
  118. if ($XHtmlFix == TRUE) {
  119. $tag = str_replace('>', ' />', $tag);
  120. }
  121. array_pop($tagStack);
  122. }
  123. }
  124. //就近闭合模式,状态变为未闭合

  125. if ('CLOSE' == $type) {
  126. $isClosed = false;
  127. }
  128. //默认的嵌套模式,如果标签位于提供的 $tagArray 里,状态改为未闭合
  129. else {
  130. if (in_array($matchLower, $tagArray)) {
  131. $isClosed = false;
  132. }
  133. }
  134. unset($matchLower);
  135. }
  136. //匹配闭合标签,如果合适则出栈

  137. else if (preg_match("/]*?>/si", $tag, $match)) {
  138. //如果参数 $lowerTag 为 TRUE 则将标签名转为小写

  139. $matchLower = $lowerTag == TRUE ? strtolower($match[1]) : $match[1];
  140. if (end($tagStack) == $matchLower) {

  141. $isClosed = true; //匹配完成,标签闭合
  142. $tag = str_replace('' . $match[1], '' . $matchLower, $tag);
  143. $result .= $tag;
  144. array_pop($tagStack);
  145. }
  146. unset($matchLower);
  147. }
  148. //匹配注释,直接连接 $result

  149. else if (preg_match("//si", $tag)) {
  150. $result .= $tag;
  151. }
  152. //将字符串放入 $result ,顺便做下截断操作

  153. else {
  154. if (is_null($length) || $len + mb_strlen($tag) $result .= $tag;
  155. $len += mb_strlen($tag);
  156. } else {
  157. $str = mb_substr($tag, 0, $length - $len + 1);
  158. $result .= $str;
  159. break;
  160. }
  161. }
  162. }
  163. //如果还有将栈内的未闭合的标签连接到 $result

  164. while (!empty($tagStack)) {
  165. $result .= '' . array_pop($tagStack) . '>';
  166. }
  167. return $result;
  168. }
  169. ?>
复制代码


source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal