假如有一段字符串,例如:
Thanks for use <a href="http://www.wordpress.com><span class="link"></span>wordpress</a>"
如果要截取前面15个字符串,那肯定没问题,如果截取的是20个字符串,那肯定就落在<a>标签里,这么一来截取后再显示取来的内容就有问题,标签不完整,可能会影响样式。
下面的方法可以解决php截取文本时,不会讲html标签截断:
/** * 字符串切割 * * 功能:截取字符串(支持中文),如果字符串中包括<a title="查看与html标签有关的文章" href="http://www.5imoban.net" target="_blank">html标签</a>,截取的字符串则会保留完整的<a title="查看与html标签有关的文章" href="http://www.5imoban.net" target="_blank">html标签</a> * 如果截取的字符串中包含不完整的html标签,则从字符串位置0开始截取到html标签前 * * @param string $string * @param int $length * @param string $replace * @return string */ function htmlSubStr ($string, $length = 0, $replace = '...') { // 先截取指定长度的字符串,支持中文 if (strlen ( $string ) < $length) { $string = substr ( $string, 0 ); } else { $char = ord ( $string [$length - 1] ); if ($char >= 224 && $char <= 239) { $string = substr ( $string, 0, $length - 1 ); } else { $char = ord ( $string [$length - 2] ); if ($char >= 224 && $char <= 239) { $string = substr ( $string, 0, $length - 2 ); } else { $string = substr ( $string, 0, $length ); } } } // 开始标签集合,当前开始标签字符串(a,span,div...),结束标签集合 $starts = $start_str = $ends = array (); // 提取截取的字符串中出现的开始标签结合和结束标签集合 preg_match_all ( '/<\w+[^>]*>?/', $string, $starts, PREG_OFFSET_CAPTURE ); preg_match_all ( '/<\/\w+>/', $string, $ends, PREG_OFFSET_CAPTURE ); // 初始化<a title="查看与字符串截取有关的文章" href="http://cuelog.com/tag/%e5%ad%97%e7%ac%a6%e4%b8%b2%e6%88%aa%e5%8f%96" target="_blank">字符串截取</a>点 $cut_pos = 0; // 最后追加的字符串 $last_str = ''; if (! empty ( $starts [0] )) { $starts = array_reverse ( $starts [0] ); if (! empty ( $ends [0] )) { $ends = $ends [0]; } foreach ( $starts as $sk => $s ) { // 判断开始标签是否包括XHTML语法的闭合标签<img alt=""> $auto = false; if ($auto != false && $auto = strripos ( $s [0], "/>' )) { // 如果有,则将<a title="查看与字符串截取有关的文章" href="http://cuelog.com/tag/%e5%ad%97%e7%ac%a6%e4%b8%b2%e6%88%aa%e5%8f%96" target="_blank">字符串截取</a>点设置为当前标签的起始位置 if ($cut_pos < $auto) { $cut_pos = $s [1]; $last_str = $s [0]; unset ( $starts [$sk] ); } } else { // 提取开始标签名:a,div,span... preg_match ( '/<(\w+).*>?/', $s [0], $start_str ); if (! empty ( $ends )) { foreach ( $ends as $ek => $e ) { // 提取结束标签名 $end_str = trim ( $e [0], '</>' ); // 如果开始标签名与结束标签名一致,并且结束标签的索引值比开始标签的索引值大,则该标签是完整的有效. if ($end_str == $start_str [1] && $e [1] > $s [1]) { // 如果字符串截取点还没有确定,给它赋值 if ($cut_pos < $e [1]) { $cut_pos = $e [1]; // 并且将闭合标签作为最后的字符串追加 $last_str = $e [0]; } // 将这个正确的标签去掉结束标签,并且滚入下一个开始标签的判断 unset ( $ends [$ek] ); break; } } } else { /* * 如果empty($ends),说明第一个开始标签没有对应的闭合标签 说明这一段截取的内容不完整,只能将字符串截取到第一个开始标签前为止 */ $last_str = ''; $cut_pos = $s [1]; } } } // 拼凑剩余的字符串 $res_str = substr ( $string, 0, $cut_pos ) . $last_str; $less_str = substr ( $string, strlen ( $res_str ) ); $less_pos = strpos ( $less_str, '<' ); $less_str = $less_pos !== false ? substr ( $less_str, 0, $less_pos ) : $less_str; $string = $res_str . $less_str . $replace; } return $string; } $str = 'Welcome to hello world,<div class="http://www.baidu.com" class="title">Hey, guys..<b>Hello</b>Look at thie picture<img src="http://www.baidu.com/test.jpg" class="image" /><span><a href="#">Just so so..</a></span></div>Yeah, U R right.<div class="footer">About</div><span>Follow us..<a href="http://www.facebook.com">FB</a></span>'; echo htmlSubStr ( $str, 260 ); // Welcome to hello world,<div class="http://www.baidu.com" class="title">Hey, guys..<b>Hello</b>Look at thie picture<img src="http://www.baidu.com/test.jpg" class="image" /><span><a href="#">Just so so..</a></span></div>Yeah, U R right.<div class="footer">About<