请选择 进入手机版 | 继续访问电脑版
绿茶科技社区
实现内容:截断一段含有HTML代码的文本,但是不会出现围堵标记没有封闭的问题。
说明:这是PHP版的,用于在服务器端使用,如果你需要一个客户端版的,请阅读下一篇  
我们在写BLOG这样的程序时经常需要显示文章前一部分的,但是又怕不恰当的截断破坏封闭标签以造成整个文档结构破坏,使用我的函数可以在要求不高的情况下解决这个问题。
大家应该考虑这个函数在服务端应用还是在客户端应用。因为我考虑这个函数可能运行起来比较费机器,所以安全性要求不高的情况下可以放在客户端上。
最好数据表中单独一个字段放这个摘要,这样相应的数据库查询也优化了。牺牲一点点空间换很多时间还是划算的。
再聊一下安全性问题,主要是内容安全性。如果客户端意图更改正常的摘要信息的话,一般都是BLOG的主人才有这个权力,那么他使得摘要和原文的一致性破坏就是他自己的事了。内容以外的安全性都可以在服务端解决。所以还是推荐在客户端使用本函数。
核心代码

  1. // PHP 4.3 or above needed  
  2. define("BRIEF_LENGTH", 800);     //Word amount of the Briefing of an Article  
  3. function Generate_Brief($text){  
  4.   global $Briefing_Length;  
  5.   if(strlen($text) <= BRIEF_LENGTH ) return $text;     
  6.   $Foremost = substr($text, 0, BRIEF_LENGTH);  
  7.   $re = "/<(\/?)(P|DIV|H1|H2|H3|H4|H5|H6|ADDRESS|PRE|TABLE|TR|TD|TH|INPUT|SELECT|TEXTAREA|OBJECT|A|UL|OL|LI|BASE|META|LINK|HR|BR|PARAM|IMG|AREA|INPUT|SPAN)[^>]*(>?)/i";  
  8.   $Single = "/BASE|META|LINK|HR|BR|PARAM|IMG|AREA|INPUT/i";     
  9.   $Stack = array(); $posStack = array();  
  10.   preg_match_all($re,$Foremost,$matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE);  
  11.   /*   [Child-matching Specification]:  
  12.     $matches[$i][1] : A "/" charactor indicating whether current "<...>" Friction is Closing Part  
  13.     $matches[$i][2] : Element Name.  
  14.     $matches[$i][3] : Right > of a "<...>" Friction   */  
  15.   for($i = 0 ; $i < count($matches); $i++){  
  16.     if($matches[$i][1][0] == ""){  
  17.         $Elem = $matches[$i][2][0];  
  18.         if(preg_match($Single,$Elem) && $matches[$i][3][0] !=""){  
  19.           continue;  
  20.         }  
  21.         array_push($Stack, strtoupper($matches[$i][2][0]));  
  22.         array_push($posStack, $matches[$i][2][1]);           
  23.         if($matches[$i][3][0] =="") break;  
  24.     }else{  
  25.         $StackTop = $Stack[count($Stack)-1];  
  26.         $End = strtoupper($matches[$i][2][0]);  
  27.         if(strcasecmp($StackTop,$End)==0){  
  28.           array_pop($Stack);  
  29.           array_pop($posStack);  
  30.           if($matches[$i][3][0] ==""){  
  31.             $Foremost = $Foremost.">";  
  32.           }  
  33.         }  
  34.     }      
  35.   }  
  36.   $cutpos = array_shift($posStack) - 1;     
  37.   $Foremost = substr($Foremost,0,$cutpos);  
  38.   return $Foremost;  
  39. };
复制代码
若遇到问题(发现上面的函数对多字节字符集支持得不好) 不烦试试下面的这个!

  1. function Generate_Brief($text){  
  2.   global $Briefing_Length;  
  3.   mb_regex_encoding("UTF-8");  
  4.   if(mb_strlen($text) <= BRIEF_LENGTH ) return $text;     
  5.   $Foremost = mb_substr($text, 0, BRIEF_LENGTH);  
  6.   $re = "<(\/?)(P|DIV|H1|H2|H3|H4|H5|H6|ADDRESS|PRE|TABLE|TR|TD|TH|INPUT|SELECT|TEXTAREA|OBJECT|A|UL|OL|LI|BASE|META|LINK|HR|BR|PARAM|IMG|AREA|INPUT|SPAN)[^>]*(>?)";  
  7.   $Single = "/BASE|META|LINK|HR|BR|PARAM|IMG|AREA|INPUT|BR/i";     
  8.   $Stack = array(); $posStack = array();  
  9.   mb_ereg_search_init($Foremost, $re, 'i');  
  10.   while($pos = mb_ereg_search_pos()){  
  11.     $match = mb_ereg_search_getregs();  
  12.     /*   [Child-matching Formulation]:  
  13.         $matche[1] : A "/" charactor indicating whether current "<...>" Friction is Closing Part  
  14.         $matche[2] : Element Name.  
  15.         $matche[3] : Right > of a "<...>" Friction     
  16.     */  
  17.     if($match[1]==""){  
  18.         $Elem = $match[2];  
  19.         if(mb_eregi($Single, $Elem) && $match[3] !=""){  
  20.           continue;  
  21.         }  
  22.         array_push($Stack, mb_strtoupper($Elem));  
  23.         array_push($posStack, $pos[0]);           
  24.     }else{  
  25.         $StackTop = $Stack[count($Stack)-1];  
  26.         $End = mb_strtoupper($match[2]);  
  27.         if(strcasecmp($StackTop,$End)==0){  
  28.           array_pop($Stack);  
  29.           array_pop($posStack);  
  30.           if($match[3] ==""){  
  31.             $Foremost = $Foremost.">";  
  32.           }  
  33.         }  
  34.     }  
  35.   }  
  36.   $cutpos = array_shift($posStack) - 1;     
  37.   $Foremost = mb_substr($Foremost,0,$cutpos,"UTF-8");  
  38.   return $Foremost;  
  39. };
复制代码


分享到 :
0 人收藏

3 个回复

倒序浏览
施杨  金牌会员 | 2019-8-13 09:25:20
佩服佩服!
魏琼东  高级会员 | 2019-8-26 02:22:11
众里寻他千百度,蓦然回首在这里!
北岛函  高级会员 | 2019-9-11 16:55:13
回个帖子,下班咯~
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

举报|Archiver|手机版|小黑屋|Lvchakeji Inc.  

Powered by Discuz! X3.3 © 2001-2016 Comsenz Inc.

返回顶部