|
发表于 2011-11-2 21:35:32
|
显示全部楼层
本帖最后由 qi_ruo 于 2011-11-2 22:23 编辑
PHP复制代码 $str = 'aaaa<div>bbbb<p>cccc<a href="#" alt="dddd">eeee<img src="pic.jpg">ffff</a>gggg<br /><br /></p>hhhh</divuuuu';
function fix_html ($string)
{
//关闭自闭合标签
$startPos = strrpos($string, "<"); //查找最后一个 < 的位置
if (false == $startPos)
{
return $string; //如果字符串中没有 < 便签 直接返回 不再检查
}
$trimString = substr($string, $startPos); // 从最后一个 < 到字符串结尾
if (false === strpos($trimString, ">"))
{
$string = substr($string, 0, $startPos); //如果之间没有 > 便签 那这一段就不要了
}
//非自闭合html标签列表
preg_match_all("/<([_0-9a-zA-Z-\:]+)\s*([^>]*)>/is", $string, $startTags);
//第一个括号匹配标签名 第二个括号匹配属性
//$startTags[1] 将存放所有起始标签的名字, 比如 [div, p, a, img, br]
//$startTags[2] 将存放所有起始标签的属性, 比如 ['', '', 'href="#"', 'src="pic.jpg" / ', '/']
preg_match_all("/<\/([_0-9a-zA-Z-\:]+)>/is", $string, $closeTags);
//$closeTags[1] 将存放所有结束标签的名字 比如 [a, p]
if (!empty($startTags[1]) && is_array($startTags[1])) // 如果$startTags[1]为空的话 说明没有找到起始标签
{
krsort($startTags[1]); // 把$startTags[1]倒序排列 以便和结束标签对应处理 可以想象成一种栈的结构
$closeTagsIsArray = is_array($closeTags[1]);
foreach ($startTags[1] as $key => $tag)
{
$attrLength = strlen($startTags[2][$key]); //该起始标签属性的长度
if ($attrLength > 0 && "/" == trim($startTags[2][$key][$attrLength - 1])) // 要么属性的最后一个字符是 /
{
continue; // 如果属性的最后一个字符为 / 比如 <img /> 继续
}
if (!empty($closeTags[1]) && $closeTagsIsArray) // 要么有结束标签
{
if (false !== ($index = array_search($tag, $closeTags[1]))) // 能找到对应的结束标签
{
unset($closeTags[1][$index]); // 从结束标签列表中去除
continue;
}
}
$string .= "</{$tag}>"; // 到此说明没有结束标签 加上结束标签
}
}
return preg_replace("/\<br\s*\/\>\s*\<\/p\>/is", '</p>', $string); // 如果 </p> 之前有<br /> 删除之, 但只删一个
}
复制代码
但也有些问题
比如 如果img 标签 写成了 <img src="#"> 程序会修正为 <img src="#"></img> 而不是 <img src="#" />
该函数的功能只是负责标签合闭,也可以进一步完善,
可以参考http://www.barattalo.it/html-fixer/
|
|