/*** 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://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);}//匹配注释,直接连接 $resultelse 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;}}}//如果还有将栈内的未闭合的标签连接到 $resultwhile (!empty($tagStack)) {$result .= '' . array_pop($tagStack) . '>';}return $result;}?>复制代码
相关文章
- PHP编程数据导入导出怎么学_PHP数据编程学习【详解】
- PHP 中通过 cURL 访问 Docker Socket 的权限问题解决方案
- 欧艺OKE交易所app下载 欧艺OKX官网最新手机App安装地址
- 怎么在Golang中模拟引用传递_Golang指针参数与结构体指针用法
- ThinkPHP5.0集成Workerman WebSocket服务无法连接:问题在哪儿以及如何解决?
- 解决Render云部署中Alembic“可执行文件未找到”错误
- 如何在PHP中使用数组(附代码示例)
- Go 中匿名函数捕获循环变量的陷阱与正确解决方案
- 详解php中反射的应用,详解php反射应用_PHP教程
- Django常量翻译与AppRegistryNotReady错误解决方案
