作者:苏林 来源:CSDN博客   酷勤网收集 2008-07-12

摘要
  比如对字符串中的“&”,在进行第一次编码后,它将变为“&”。在第二次编码时,在对“&”进行替换后,将把“&”中的“&”再次换成“&”,于是得到“&”……

    在html中,有些字符是用于做特殊标记的,比如“<”。当需要在界面上显示这些字符时,就需要用另外一种方法来表示,比如“<”要表示为“&lt;”。只要知道了html中各个符号替代字符串,写一个这样的函数算不上什么难事,可是有人却偏偏画蛇添足,并把添了足的代码放到了网上,结果使很多网站出错。

这段代码被放在一个名为《一些非常有用的Java常用方法》的帖子中。这个帖子被广泛转载,可以在很多技术网站找到它。不过因为很多网站自身可能也使用了帖子中的代码,所以这些网站都无法把这个帖子正确地表现出来。在我找了很久之后,终于找到了这帖子的本来面目。我现在把这帖子的原始内容贴出来,再把那些出错了的网站的中,该帖子的内贴出来,做个对比。原帖中的htmlEncode函数如下(代码1Java语言,下同):

  1. String htmlEncode(String txt)   
  2.   
  3. {   
  4.   
  5.    txt = replace(txt,"&","& amp;");   
  6.   
  7.   txt = replace(txt,"& amp;amp;","& amp");   
  8.   
  9.   txt = replace(txt,"& amp;quot;","& quot;");     
  10.   
  11.   txt = replace(txt,"\"","& quot;");    
  12.   
  13.   txt = replace(txt,"& amp;lt;","& lt;");    
  14.   
  15.   txt = replace(txt,"<","& lt;");    
  16.   
  17.   txt = replace(txt,"& amp; gt;","& gt;");    
  18.   
  19.   txt = replace(txt,">","& gt;");    
  20.   
  21.   txt = replace(txt,"& amp;nbsp;","& nbsp");    
  22.   
  23.   txt = replace(txt," ","& nbsp");    
  24.   
  25.   return txt;    
  26.   
  27. }   
  28.   
  29.   
  30. <SPAN lang=EN-US> </SPAN>  

使用Google搜到的大多网站上的帖子中,该函数的内容如下(代码2):

  1. <PRE class=csharp name="code">String htmlEncode(String txt){   
  2.   
  3.   txt = replace(txt,"&","&");   
  4.   
  5.   txt = replace(txt,"& amp;","&");   
  6.   
  7.   txt = replace(txt,"& quot;","\"");   
  8.   
  9.   txt = replace(txt,"\"",""");   
  10.   
  11.   txt = replace(txt,"& lt;","<");   
  12.   
  13.   txt = replace(txt,"<","<");   
  14.   
  15.   txt = replace(txt,"& gt;",">");   
  16.   
  17.   txt = replace(txt,">",">");   
  18.   
  19.   txt = replace(txt,"& nbsp;"," ");   
  20.   
  21.   txt = replace(txt," "," ");   
  22.   
  23.   return txt;   
  24.   
  25. }   
  26.   
  27. </PRE>  
在这两段代码中replace是自定义的字符串内替换函数,这个我们先不管它。且看第二段代码中,有很多第2个参数和第3个参数相同的replace调用,不觉得很奇怪么?

在读过了很多这样奇怪代码的帖子之后,终于在一个网站上找到了正确的原始帖子,看到了这个htmlEncode函数的真面目,也就是代码1中的内容。

其实看代码1也有奇怪之处。按一般的想法,只要把“& < > \ ”等这几个字符逐一替换成相应的替代字符串就可以了,怎么会有如txt = replace(txt,"&amp;amp;","&amp;");这样的语句呢?

后来一想,我明白了,作者是想让编码过的字符串不被重复编码。可能作者在程序的很多地方对字符串进行htmlEncode编码操作,他希望第一次编码后,其它的编码操作不再起作用,这样他只进行一次解码就可以还原原来的内容。

比如对字符串中的“&”,在进行第一次编码后,它将变为“&amp;”。在第二次编码时,在对“&”进行替换后,将把“&amp;”中的“&”再次换成“&amp;”,于是得到“&amp;amp;”。作者为了不重复编码,就在txt = replace(txt,"&","&amp;");语句之后,又加了一句txt = replace(txt,"&amp;amp;","&amp;");把内容再替换回来。

同理,后面的txt = replace(txt,"&amp;quot;","&quot;");等类似语句也是为了达到这个目的加上去的。

作者写完这个程序之后一定很得意:看我这个程序多好,不会重复编码,调用100htmlEncode也没关系,总能得到同一个结果!

可惜,这个结果并非总是正确的!试想,如果我想在网页上输出字符串"&amp;",正如要显示作者的这个帖子所需要的那样,在内容中直接显示"&amp;",问题来了:我对字符串"&amp;"调用htmlEncode之后,得到的还是"&amp;",我把"&amp;"放到html中时,页面上只会显示一个”&”,而不是"&amp;"。对于其它内容也一样,“&lt;”、“&lg;”、“&gt;”等这样的字符串都无法显示正确显示。

呵呵,这也正解释了为什么这么多网站会把作者的代码显示成代码2所示那样,因为他们都用了作者的程序。就拿作者帖子中的代码的第一句为例:

原文为:txt = replace(txt,"&","&amp;");

 

使用作者的算法对这段内容进行htmlEncode,得到:

txt = replace(txt, &quot;&amp; &quot;, &quot;&amp; &quot;);

 

前一个“&”被替换为“&amp;”,而第二个参数&amp;不变。把这段代码放在html中送到浏览器,正好显示为:

txt = replace(txt,"&","&");

 

代码中其它的那些第2、3参数相同的replace调用也都是因为这个原因。

一句话,作者想优化html编码的功能,结果画蛇添足。

 

把代码改成如下的形式,去掉那些“足”,就可以正确编码了:

  1. String htmlEncode(String txt)   
  2.   
  3. {   
  4.   
  5.    txt = replace(txt,"&","& amp;");    
  6.   
  7.   txt = replace(txt,"\"","& quot;");    
  8.   
  9.   txt = replace(txt,"<","& lt;");   
  10.   
  11.   txt = replace(txt,">","& gt;");   
  12.   
  13.   txt = replace(txt," ","& nbsp;");    
  14.   
  15.   return txt;    
  16.   
  17. }  

从编程的角度看,这只是个画蛇添足的问题。如果换个角度,还有一些有意思的事情:

一、很多网站都使用了这段代码,并因此而无法正确显示作者的帖子,可见网络上错误信息的危害,并提醒大家在使用网络上的代码时,一定加倍小心。

二、这段代码自己的错误导致了网站无法正确显示这段代码本身,这也限制了这段代码的使用。这算是网络自然法则么:正确的事物得以发展,不正确的自取灭亡?

希望CSDN没有使用这样的代码,否则我这个文章的内容也无法显示了。如果您转帖了本文,请千万检查一下,贴过去之后,内容还能正确显示否!

update:
哈哈,事实证明,CSND的网站程序中也用了这段出错的代码。文章的摘要显示中就不正常, 文章内容中的代码部分也不正常。 为此,我只好在所有的&后面加了个空格, 以求正确显示。

 来自:http://blog.csdn.net/Slin000/archive/2008/07/07/2621107.aspx

分类: 网页设计 站长经验 Web开发 交互设计 艺术设计

上一篇:新浪、网易、腾讯等门户们改版之后的首页浅谈   下一篇:Christopher Schmitt 谈学习CSS的益处