php html标签闭合,PHP 修复未正常关闭的HTML标签实现代码(支持嵌套和就近闭合)

fixHtmlTag

version 0.2

这个版本解决了上次遗留的问题,即就近闭合和嵌套闭合问题。具体可以看代码的注释。

/**

* fixHtmlTag

*

* HTML标签修复函数,此函数可以修复未正确闭合的 HTML 标签

*

* 由于不确定性因素太多,暂时提供两种模式“嵌套闭合模式”和

* “就近闭合模式”,应该够用了。

*

* 这两种模式是我为了解释清楚此函数的实现而创造的两个名词,

* 只需明白什么意思就行。

* 1,嵌套闭合模式,NEST,为默认的闭合方式。即 "

你好"

* 这样的 html 代码会被修改为 "

你好
"

* 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不倒翁

* @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(

'

'

'

'

'


'

'

);

//校验匹配模式 $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) < $length) {

$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;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值