PHP 修复未正常关闭的HTML标签实现代码(支持嵌套和就近闭合)
|
fixHtmlTag 2,就近闭合模式,CLOSE,这种模式会将形如 " 你好 为什么没有 你好 为什么没有闭合呢 "在嵌套闭合模式(默认,无需特殊传参)下,可以传入需要就近闭合的 标签名,通过这种方式将类似 " 你好 我也好" 转换为 你好 我也好 "的形式。传参时索引需要按照如下方式写,不需要修改的设置可以省略 $param = array( 'html' => '',//必填 'options' => array( 'tagArray' => array(); 'type' => 'NEST', 'length' => null, 'lowerTag' => TRUE, 'XHtmlFix' => TRUE, ) ); fixHtmlTag($param); 上面索引对应的值含义如下 string $html 需要修改的 html 代码 array $tagArray 当为嵌套模式时,需要就近闭合的标签数组 string $type 模式名,目前支持 NEST 和 CLOSE 两种模式,如果设置为 CLOSE,将会忽略参数 $tagArray 的设置,而全部就近闭合所有标签 ini $length 如果希望截断一定长度,可以在此赋值,此长度指的是字符串长度 bool $lowerTag 是否将代码中的标签全部转换为小写,默认为 TRUE bool $XHtmlFix 是否处理不符合 XHTML 规范的标签,即将 转换为 @author IT不倒翁 itbudaoweng@gmail.com @version 0.2 @link http://yungbo.com IT不倒翁 @link http://enenba.com/?post=19 某某 @param array $param 数组参数,需要赋予特定的索引 @return string $result 经过处理后的 html 代码 @since 2012-04-14 / function fixHtmlTag($param = array()) { //参数的默认值 $html = ''; $tagArray = array(); $type = 'NEST'; $length = null; $lowerTag = TRUE; $XHtmlFix = TRUE; //首先获取一维数组,即 $html 和 $options (如果提供了参数) extract($param); //如果存在 options,提取相关变量 if (isset($options)) { extract($options); } $result = ''; //最终要返回的 html 代码 $tagStack = array(); //标签栈,用 array_push() 和 array_pop() 模拟实现 $contents = array(); //用来存放 html 标签 $len = 0; //字符串的初始长度 //设置闭合标记 $isClosed,默认为 TRUE,如果需要就近闭合,成功匹配开始标签后其值为 false,成功闭合后为 true $isClosed = true; //将要处理的标签全部转为小写 $tagArray = array_map('strtolower',$tagArray); //“合法”的单闭合标签 $singleTagArray = array( '<meta', '<link', '<base', '<br', '<hr', '<input', '<img' ); //校验匹配模式 $type,默认为 NEST 模式 $type = strtoupper($type); if (!in_array($type,array('NEST','CLOSE'))) { $type = 'NEST'; } //以一对 < 和 > 为分隔符,将原 html 标签和标签内的字符串放到数组中 $contents = preg_split("/(<[^>]+?>)/si",$html,-1,PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE); foreach ($contents as $tag) { if ('' == trim($tag)) { $result .= $tag; continue; } //匹配标准的单闭合标签,如 if (preg_match("/<(w+)[^/>]?/>/si",$tag)) { $result .= $tag; continue; } //匹配开始标签,如果是单标签则出栈 else if (preg_match("/<(w+)[^/>]?>/si",$tag,$match)) { //如果上一个标签没有闭合,并且上一个标签属于就近闭合类型 //则闭合之,上一个标签出栈 //如果标签未闭合 if (false === $isClosed) { //就近闭合模式,直接就近闭合所有的标签 if ('CLOSE' == $type) { $result .= '</' . end($tagStack) . '>'; array_pop($tagStack); } //默认的嵌套模式,就近闭合参数提供的标签 else { if (in_array(end($tagStack),$tagArray)) { $result .= '</' . end($tagStack) . '>'; array_pop($tagStack); } } } //如果参数 $lowerTag 为 TRUE 则将标签名转为小写 $matchLower = $lowerTag == TRUE ? strtolower($match[1]) : $match[1]; $tag = str_replace('<' . $match[1],'<' . $matchLower,$tag); //开始新的标签组合 $result .= $tag; array_push($tagStack,$matchLower); //如果属于约定的的单标签,则闭合之并出栈 foreach ($singleTagArray as $singleTag) { if (stripos($tag,$singleTag) !== false) { if ($XHtmlFix == TRUE) { $tag = str_replace('>',' />',$tag); } array_pop($tagStack); } } //就近闭合模式,状态变为未闭合 if ('CLOSE' == $type) { $isClosed = false; } //默认的嵌套模式,如果标签位于提供的 $tagArray 里,状态改为未闭合 else { if (in_array($matchLower,$tagArray)) { $isClosed = false; } } unset($matchLower); } //匹配闭合标签,如果合适则出栈 else if (preg_match("/</(w+)[^/>]?>/si",$match)) { //如果参数 $lowerTag 为 TRUE 则将标签名转为小写 $matchLower = $lowerTag == TRUE ? strtolower($match[1]) : $match[1]; if (end($tagStack) == $matchLower) { $isClosed = true; //匹配完成,标签闭合 $tag = str_replace('</' . $match[1],'</' . $matchLower,$tag); $result .= $tag; array_pop($tagStack); } unset($matchLower); } //匹配注释,直接连接 $result else if (preg_match("/<!--.?-->/si",$tag)) { $result .= $tag; } //将字符串放入 $result ,顺便做下截断操作 else { if (is_null($length) || $len + mb_strlen($tag) < $length) { $result .= $tag; $len += mb_strlen($tag); } else { $str = mb_substr($tag,$length - $len + 1); $result .= $str; break; } } } //如果还有将栈内的未闭合的标签连接到 $result while (!empty($tagStack)) { $result .= '</' . array_pop($tagStack) . '>'; } return $result; } (编辑:安卓应用网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
