'', //必填 * '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不倒翁 * @version 0.2 * @link http://bbs.it-home.org 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( ''''
''');//校验匹配模式 $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(/]*?\/>/si, $tag)) { $result .= $tag; continue; }//匹配开始标签,如果是单标签则出栈
else if (preg_match(/]*?>/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('//开始新的标签组合
$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(/]*?>/si, $tag, $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) $result .= $tag; $len += mb_strlen($tag); } else { $str = mb_substr($tag, 0, $length - $len + 1); $result .= $str; break; } } }//如果还有将栈内的未闭合的标签连接到 $result
while (!empty($tagstack)) { $result .= '' . array_pop($tagstack) . '>'; } return $result; }?>
复制代码