免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2778 | 回复: 8
打印 上一主题 下一主题

[正则]html字串过滤问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2005-11-26 14:40 |只看该作者 |倒序浏览
假设有一html字串

<a href="http://www.baidu.com" alt="baidu search" target="_blank">baidu.com</a>
<p style="font-size:14px;" align="right">asdfdfasdfasdf</p>
<font color="#00ff77" style="font-size:14px">afasdfasdfasd</font>


要将<a>标记只保留href和target属性
  将<p>标记只保留align属性
  将<font>标记只保留color属性

字串的内容并不限于此格式,可能还有很多其它的格式,如
<a target=_parent style="font-color:#cccccc;" href='http://www.baidu.com' alt='baidu'>baidu</a>


替换后的内容如下
<a href="http://www.baidu.com" target="_blank">baidu.com</a>
<p align="right">asdfdfasdfasdf</p>
<font color="#00ff77">afasdfasdfasd</font>

请大家给个思路或相关解决代码,谢谢.

论坛徽章:
0
2 [报告]
发表于 2005-11-26 15:22 |只看该作者


  1. $str = <<<HTML
  2. <a href="http://www.baidu.com" alt="baidu search" target="_blank">baidu.com</a>
  3. <p style="font-size:14px;" align="right">asdfdfasdfasdf</p>
  4. <font color="#00ff77" style="font-size:14px">afasdfasdfasd</font>
  5. HTML;

  6. $strResult = preg_replace("/<a href=([^ ]*)(.*)( target=[^ ]*)>(.*)<\/a>/i",'<a href=\1\3>\4</a>',$str);
  7. $strResult = preg_replace("/<p(.*)( align=([^ ]*))(.*)>(.*)<\/p>/i",'<p\2>\5</p>',$strResult);
  8. $strResult = preg_replace("/<font(.*)( color=([^ ]*))(.*)>(.*)<\/font>/i",'<font\2>\5</font>',$strResult);

复制代码

论坛徽章:
0
3 [报告]
发表于 2005-11-26 16:42 |只看该作者
谢谢楼上的代码,代码运行是正常的,可以解决上面固定格式字串的,但有的时候字串的格式变了就不行,通用性还有点不好

如:<a alt="baidu search"  href="http://www.baidu.com" target="_blank">baidu.com</a>
的时候就没过滤alt属性

怎么写个通用的呢

论坛徽章:
1
技术图书徽章
日期:2013-12-05 23:25:45
4 [报告]
发表于 2005-11-27 15:01 |只看该作者
http://bbs.chinaunix.net/viewthread.php?tid=642112

可以参考这个做href的部分

其他的类比进行做。

你这个要求太复杂了,不专门处理做不好。

论坛徽章:
0
5 [报告]
发表于 2005-11-28 10:09 |只看该作者
唉,这个问题很想了一会,昨天晚上吃饭的时候想到一个办法:

1>传递一个参数给要过滤的函数
2>过滤函数根据要保留的标记属性来preg_replace,把要保留的属性
 移位到前面去
3>再进行preg_replace替换,这样有多个保留属性的时候就不会出乱

这是饭后写的一点代码,估计还不是很完善,我觉得也没什么效率可言,只不过是能满足我的要求



  1. <?php
  2. /*****************************************
  3. * 原文件名:HtmlFilter.php
  4. * 文件说明:过滤HTML字串
  5. * 文件编写:xuefengal@sohu.com
  6. ****************************************/

  7. $str = <<< HTML
  8.     <A style="asdf" href="http://www.google.com" target="_blank" alt="Google">Google搜索</A>
  9.     <A href="http://www.google.com" target="_blank" alt="Google" style="asdf">Google搜索</A>
  10.     <A target="_blank" href="http://www.google.com" style="asdf" alt="Google">Google搜索</A>
  11.     <P align="right" style="font-color:red;">abc</P>
  12.     <P style="font-color:red;" align="right">abc</P>
  13.     <FONT color="#ffffff" face="Simsun" class="c12">测试</FONT>
  14.     <FONT color="#ffffff" class="c12" face="Simsun">测试</FONT>
  15.     <FONT class="c12" color="#ffffff" face="Simsun">测试</FONT>
  16.     <div align="left">asdfadfadf</div>
  17. HTML;

  18. //过滤换前
  19. disp($str,'原字串');

  20. $debug = 0;

  21. //过滤
  22. filter('a','href,target',$str,$debug);
  23. filter('p','align',$str,$debug);
  24. filter('font','color',$str,$debug);
  25. filter('div','align',$str,$debug);

  26. //过滤后
  27. disp($str,'替换后的字串');

  28. /**
  29. * 函数功能:过滤HTML标记
  30. * 参数说明:
  31. *           $flag:为要过滤的标记,如
  32. *           a,p代表<a xxx>xxx</a>,<p xxx>xxx</p>
  33. *
  34. *           $arr:为要保留的属性,参数可以如下形式
  35. *           href
  36. *           array('href','target')
  37. *           href,target,alt
  38. *
  39. *           $str:要过滤的字串
  40. *           $debug:是否显示配置信息
  41. *
  42. * 运行流程:首先判断传递进来的$arr参数是字串还是数组,
  43. *           是字串的时候构建成数组的形式,然后foreach
  44. *           该数组(其实可以不用这样,但懒得复制代码,就
  45. *           转换成数组了),将要保留属性逐位移动到<a 的
  46. *           后面,同时保存此属性的替换正则,完成所有循环
  47. *           后再进行一次全替换,替换完后补全相关标记的
  48. *           格式,如<a及后面的>title</a>.即完成
  49. */
  50. function filter($flag,$arr,&$str,$debug = False) {

  51.     echo("<hr><h3>过滤 $flag 标记</h3><hr><br>");

  52.     //保存最后执行一次性替换的正则
  53.     $final_reg = "";
  54.     //保存最后要保留的属性值的正则
  55.     $hold_val = '';
  56.    
  57.     if(!is_array($arr)) {
  58.         //没有传递数组进来时判断参数是否包含,号
  59.         if(strpos($arr,',')) {
  60.             //包含,号时,切分参数串为数组
  61.             $arr = explode(',',$arr);
  62.         }else {
  63.             //纯字串,构造数组
  64.                 $arr = array($arr);
  65.         }
  66.         
  67.     }

  68.     //循环替换
  69.     if(is_array($arr)) {
  70.         foreach($arr as $key=>$val) {
  71.             //逐个将属性提前,如下
  72.             //原匹配部分:<a alt="xxx" href=xxx.htm>xxxxx</a>
  73.             //要保留属性:href
  74.             //提前该属性位置后的匹配内容如下:
  75.             //           <a href=xxx.htm alt="xxx">xxxxx</a>
  76.             $reg = "/(<$flag)(.*)( $val=([^ ]*))(.*)(>)(.*)(<\/$flag>)/i";

  77.             //调试信息
  78.             disp($reg,'匹配['.$val.']属性的正则',$debug);
  79.             preg_match_all($reg,$str,$out);
  80.             disp(print_r($out,true),'匹配['.$val.']结果',$debug);

  81.             //将此保留属性位置移到<a的最前面
  82.             $str = preg_replace($reg,'\1\3\2\5\6\7\8',$str);

  83.             //调试信息
  84.             disp($str,'移位['.$val.']属性后的字串',$debug);

  85.             //保存此正则
  86.             $final_reg = "( $val=([^ ]*))".$final_reg;
  87.             //保存保留部分,此部分是跟据$final_reg的正则"( $val=([^ ]*))"而来
  88.             $hold_val = '\\'.(($key+1)*2).$hold_val;
  89.             
  90.         }

  91.         //构成最后替换的正则
  92.         $final_reg = "/(<$flag)".$final_reg."(.*)(>)(.*)(<\/$flag>)/i";
  93.         //调试信息
  94.         disp($final_reg,'最后一次性替换['.$flag.']标记的正则',$debug);
  95.         preg_match($final_reg,$str,$out);
  96.         disp(print_r($out,true),'匹配['.$flag.']属性部分',$debug);

  97.         //计算最后>xxxx</a>部分,一个标记可能有很多属性,所以就用
  98.         //count($out)的值来取$out的最后三个$key,构成正则部分
  99.         $cnt = count($out);
  100.         $hold_val .= '\\'.($cnt-3).'\\'.($cnt-2).'\\'.($cnt-1);
  101.         //在保存正则前加上前面已保留匹配的部分
  102.         $hold_val = '\1'.$hold_val;
  103.         //现在保留部分正则已形成如下格式
  104.         //\1\3\5\7\8\9

  105.         //调试信息
  106.         disp('preg_replace("'.$final_reg.'",\''.$hold_val.'\',$str);','替换['.$flag.']标记的正则',True);

  107.         //最后过滤
  108.         $str = preg_replace($final_reg,$hold_val,$str);

  109.         //调试信息
  110.         disp($str,'最后替换['.$flag.']标记的结果',$debug);
  111.         
  112.     }
  113. }

  114. /**
  115. * 显示字串内容
  116. */
  117. function disp($str,$title='',$debug = True) {

  118.    if($debug) {
  119.        //根据要显示字串的行数来设定txtarea的rows
  120.        $txtRows = count(explode("\n",$str));
  121.        echo($title.':<br><TEXTAREA NAME="txt" ROWS="'.$txtRows.'" COLS="130">'.$str.'</TEXTAREA><br><br>');
  122.    }

  123. }


  124. ?>

复制代码

论坛徽章:
1
技术图书徽章
日期:2013-12-05 23:25:45
6 [报告]
发表于 2005-11-28 10:16 |只看该作者
建议你看这个:

http://w.yi.org/ftp/FAPM/PHP/php ... preg-match-all.html

先获取属性列表,然后分析。

论坛徽章:
0
7 [报告]
发表于 2005-11-28 10:18 |只看该作者

  1. 原字串:<br><TEXTAREA NAME="txt" ROWS="9" COLS="130">
  2.     <A style="asdf" href="http://www.google.com" target="_blank" alt="Google">Google搜索</A>
  3.     <A href="http://www.google.com" target="_blank" alt="Google" style="asdf">Google搜索</A>
  4.     <A target="_blank" href="http://www.google.com" style="asdf" alt="Google">Google搜索</A>
  5.     <P align="right" style="font-color:red;">abc</P>
  6.     <P style="font-color:red;" align="right">abc</P>
  7.     <FONT color="#ffffff" face="Simsun" class="c12">测试</FONT>
  8.     <FONT color="#ffffff" class="c12" face="Simsun">测试</FONT>
  9.     <FONT class="c12" color="#ffffff" face="Simsun">测试</FONT>
  10.     <div align="left">asdfadfadf</div></TEXTAREA><br>

复制代码


  1. //过滤
  2. //a 标记只保留href,target属性
  3. //p 标记只保留align属性
  4. //font 标记保留color属性
  5. //div 标记保留align属性

  6. filter('a',array('href','target'),$str,$debug);
  7. filter('p','align',$str,$debug);
  8. filter('font','color',$str,$debug);
  9. filter('div','align',$str,$debug);

复制代码

  1. 替换后的字串:<br><TEXTAREA NAME="txt" ROWS="9" COLS="130">
  2.     <A href="http://www.google.com" target="_blank">Google搜索</A>
  3.     <A href="http://www.google.com" target="_blank">Google搜索</A>
  4.     <A href="http://www.google.com" target="_blank">Google搜索</A>
  5.     <P align="right">abc</P>
  6.     <P align="right">abc</P>
  7.     <FONT color="#ffffff">测试</FONT>
  8.     <FONT color="#ffffff">测试</FONT>
  9.     <FONT color="#ffffff">测试</FONT>
  10.     <div align="left">asdfadfadf</div></TEXTAREA><br><br>

复制代码

论坛徽章:
0
8 [报告]
发表于 2005-11-28 10:19 |只看该作者
原帖由 HonestQiao 于 2005-11-28 10:16 发表
建议你看这个:

http://w.yi.org/ftp/FAPM/PHP/php ... preg-match-all.html

先获取属性列表,然后分析。



嗯,我是用preg_match_all分析的,上面那代码可以直接运行,可以看到分析效果

论坛徽章:
0
9 [报告]
发表于 2005-11-29 09:48 |只看该作者
修正了当属性字串中包含有空格时的问题,如
alt="Google Seach" 时截取为alt="Google了




  1. <?php
  2. /********************************************************************
  3. * 原文件名:Filter1.php
  4. * 文件说明:过滤HTML字串
  5. * 文件编写:xuefengal@sohu.com
  6. * 流程说明:
  7. *           当附合要求的参数传递进filter函数后,filter()函数首先
  8. *           把要字串中所有要过滤的标签$tag通过preg_match_all()
  9. *           取出来,然后循环preg_match_all的匹配数组,通过preg_split()
  10. *           函数分割每个标签为 "左边属性" = "右边值"的形式,再从要保
  11. *           留的属性数组中循环,将preg_split()匹配的内容对应取出,构成
  12. *           可以替换的值,后最通过str_replcae()替换掉字串中相应的标签
  13. * 函数列表:
  14. *           function filter(&$str,$tag,$keep_attribute)
  15. *           function match($reg,&$str,$arr)
  16. *           function show($str,$title='',$debug = True)
  17. * 使用示例:
  18. *           //取得搜狐新闻首页
  19. *           $str = @file_get_content("http://news.sohu.com");
  20. *           //过滤
  21. *           filter($str,'a','href,target,alt');
  22. *           filter($str,'p','align');
  23. *           show($str,'过滤后的内容');
  24. ********************************************************************/

  25. $start_time = array_sum(explode(" ",microtime()));

  26. $str = <<< HTML
  27.     <A style="a" target=_blank href='http://www.a.com' xxx=xadsfa alt="a a a" style="aa">site a</A>
  28.     <A alt='b b b' xxx=xadsfa target=_blank href='http://www.b.com' style="b" style="bb">site b</A>
  29.     <A xxx=xadsfa style="c" href='http://www.c.com' target=_blank alt=c c c style="cc">site c</A>
  30.     <A style="d" href='http://www.d.com' xxx=xadsfa alt=d d d target=_blank style="dd">site d</A>
  31.     <A target=_blank style="e" xxx=xadsfa style="ee" alt=e e e href='http://www.e.com'>site e</A>

  32.     <p align=right style="font-size:10px">adasdfasdf</p>
  33.     <p style="font-color:red;" align='left'>asdfasdfasdfasdf</p>
  34.     <p align=left right center>asdfasdfasdf</p>

  35.     <font color="red" alt=adasd adsasd>asdfadsfasdf</font>
  36.     <font align='left' color=red>asdfasdfadf</font>
  37.     <font align=left right color=red black>asdfasdf</font>
  38. HTML;

  39. //显示原字串
  40. show($str,'Html');

  41. //过滤
  42. filter($str,'a','href,target,alt');
  43. filter($str,'p','align');
  44. filter($str,'font','color,alt');

  45. //显示过滤后的内容
  46. show($str,'Result');

  47. //脚本运行时间
  48. $run_time = array_sum(explode(" ",microtime())) - $start_time;
  49. echo('<center>Script Run Time: '.$run_time.'</center>');



  50. /**
  51. * 说明:过滤HTML字串
  52. * 参数:
  53. *       $str : 要过滤的HTML字串
  54. *       $tag : 过滤的标签类型
  55. *       $keep_attribute :
  56. *              要保留的属性,此参数形式可为
  57. *              href
  58. *              href,target,alt
  59. *              array('href','target','alt')
  60. */
  61. function filter(&$str,$tag,$keep_attribute) {
  62.    
  63.     //检查要保留的属性的参数传递方式
  64.     if(!is_array($keep_attribute)) {
  65.         //没有传递数组进来时判断参数是否包含,号
  66.         if(strpos($keep_attribute,',')) {
  67.             //包含,号时,切分参数串为数组
  68.             $keep_attribute = explode(',',$keep_attribute);
  69.         }else {
  70.             //纯字串,构造数组
  71.             $keep_attribute = array($keep_attribute);
  72.         }
  73.     }

  74.     echo("·过滤[$tag]标签,保留属性:".implode(',',$keep_attribute).'<br>');

  75.     //取得所有要处理的标记
  76.     $pattern = "/<$tag(.*)<\/$tag>/i";
  77.     preg_match_all($pattern,$str,$out);

  78.     //循环处理每个标记
  79.     foreach($out[1] as $key => $val) {
  80.         //取得a标记中有几个=
  81.         $cnt = preg_split('/ *=/i',$val);
  82.         $cnt = count($cnt) -1;

  83.         //构造匹配正则
  84.         $pattern = '';
  85.         for($i=1; $i<=$cnt; $i++) {
  86.             
  87.             $pattern .= '( .*=.*)';
  88.         }
  89.         //完成正则表达式形成,如/(<a)( .*=.*)( .*=.*)(>.*<\/a>/i的样式
  90.         $pattern = "/(<$tag)$pattern(>.*<\/$tag>)/i";
  91.         
  92.         //取得保留属性
  93.         $replacement = match($pattern,$out[0][$key],$keep_attribute);

  94.         //替换
  95.         $str = str_replace($out[0][$key],$replacement,$str);
  96.     }       
  97. }


  98. /**
  99. * 说明:构造标签,保留要保留的属性
  100. * 参数:$reg : pattern,preg_match的表达式
  101. *       $str : string,html字串
  102. *       $arr : array,要保留的属性
  103. * 返回:
  104. *       返回经保留处理后的标签,如
  105. *       <A href='http://www.e.com' target=_blank alt=e e e>e.com</A>
  106. */
  107. function match($reg,&$str,$arr) {
  108.    
  109.     //match
  110.         preg_match($reg,$str,$out);

  111.     //取出保留的属性
  112.     $keep_attribute = '';
  113.     foreach($arr as $k1=>$v1) {
  114.         //定义的要保留的属性的数组
  115.         foreach($out as $k2=>$v2) {
  116.             //匹配=后的数组
  117.             $attribute = trim(substr($v2,0,strpos($v2,'=')));
  118.             //=前面的
  119.             if($v1 == $attribute) {
  120.                 //要保留的属性和匹配的值的=前的部分相同
  121.                 $keep_attribute .= $v2;
  122.                 //保存此匹配部分的值
  123.             }
  124.         }

  125.     }
  126.    
  127.     //构造返回值,结构如:<a href=xxx target=xxx class=xxx>aadd</a>
  128.     $keep_attribute = $out[1].$keep_attribute.($out[count($out)-1]);
  129.     //返回值
  130.     Return $keep_attribute;
  131. }



  132. /**
  133. * 显示字串内容
  134. */
  135. function show($str,$title='',$debug = True) {

  136.    if($debug) {
  137.        if(is_array($str)) {
  138.             $str = print_r($str,True);
  139.        }
  140.        $txtRows = count(explode("\n",$str))+1;
  141.        echo($title.':<br><TEXTAREA NAME="txt" ROWS="'.$txtRows.'" COLS="130">'.$str.'</TEXTAREA><br><br>');
  142.    }

  143. }

  144. ?>
复制代码


运行结果

原字串:


  1.     <A style="a" target=_blank href='http://www.a.com' xxx=xadsfa alt="a a a" style="aa">site a</A>
  2.     <A alt='b b b' xxx=xadsfa target=_blank href='http://www.b.com' style="b" style="bb">site b</A>
  3.     <A xxx=xadsfa style="c" href='http://www.c.com' target=_blank alt=c c c style="cc">site c</A>
  4.     <A style="d" href='http://www.d.com' xxx=xadsfa alt=d d d target=_blank style="dd">site d</A>
  5.     <A target=_blank style="e" xxx=xadsfa style="ee" alt=e e e href='http://www.e.com'>site e</A>

  6.     <p align=right style="font-size:10px">adasdfasdf</p>
  7.     <p style="font-color:red;" align='left'>asdfasdfasdfasdf</p>
  8.     <p align=left right center>asdfasdfasdf</p>

  9.     <font color="red" alt=adasd adsasd>asdfadsfasdf</font>
  10.     <font align='left' color=red>asdfasdfadf</font>
  11.     <font align=left right color=red black>asdfasdf</font>
复制代码


·过滤[a]标签,保留属性:href,target,alt
·过滤[p]标签,保留属性:align
·过滤[font]标签,保留属性:color,alt

  1.     <A href='http://www.a.com' target=_blank alt="a a a">site a</A>
  2.     <A href='http://www.b.com' target=_blank alt='b b b'>site b</A>
  3.     <A href='http://www.c.com' target=_blank alt=c c c>site c</A>
  4.     <A href='http://www.d.com' target=_blank alt=d d d>site d</A>
  5.     <A href='http://www.e.com' target=_blank alt=e e e>site e</A>

  6.     <p align=right>adasdfasdf</p>
  7.     <p align='left'>asdfasdfasdfasdf</p>
  8.     <p align=left right center>asdfasdfasdf</p>

  9.     <font color="red" alt=adasd adsasd>asdfadsfasdf</font>
  10.     <font color=red>asdfasdfadf</font>
  11.     <font color=red black>asdfasdf</font>
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP