java html escape/unescape 实现

用java 实现 html 的 escape/unescape 详解

作为web开发人员,经常需要对html进行escape和 unescape,本文简单介绍一下需要转义的字符,最后给出apache commons lang 里实现的代码。

  1. 需要转义的字符

  2. html escape/unescape的实现原理

  3. apache commons lang里StringEscapeUtils及Entities的实现

  4. apache commons lang的下载
  • 需要转义的字符

常用的字符无非就是 <,>,&,”,以及’,通过下面的代码可以看到。

private static final String[][] BASIC_ARRAY = {{"quot", "34"}, // " - double-quote
{"amp", "38"}, // & - ampersand
{"lt", "60"}, // < - less-than
{"gt", "62"}, // > - greater-than

};
private static final String[][] APOS_ARRAY = {{"apos", "39"}, // XML apostrophe
};

此外还有iso8859-1的entity和html4.0的entity。

只需要替换上述几个字符通过下面几行代码可以做到。

static Hashtable html_specialchars_table = new Hashtable();
static {
html_specialchars_table.put("<","<"); html_specialchars_table.put(">",">");
html_specialchars_table.put("&","&");
}
static String htmlspecialchars_decode_ENT_NOQUOTES(String s){
Enumeration en = html_specialchars_table.keys();
while(en.hasMoreElements()){
String key = (String)en.nextElement();
String val = (String)html_specialchars_table.get(key);
s = s.replaceAll(key, val);
}
return s;
}

参考下面链接:

http://www.w3school.com.cn/tags/html_ref_entities.html

http://www.w3school.com.cn/tags/html_ref_symbols.html

http://www.w3school.com.cn/tags/html_ref_ascii.asp

HTML特殊转义字符列表

最常用的字符实体
Character Entities

显示

说明

实体名称

实体编号

半方大的空白 &ensp; &#8194;
全方大的空白 &emsp; &#8195;
不断行的空白格 &nbsp; &#160;
< 小于 &lt; &#60;
> 大于 &gt; &#62;
& &符号 &amp; &#38;
双引号 &quot; &#34;
© 版权 &copy; &#169;
® 已注册商标 &reg; &#174;
商标(美国) &#8482;
× 乘号 &times; &#215;
÷ 除号 &divide; &#247;

ISO 8859-1 (Latin-1)字符集

HTML 4.01 支持 ISO 8859-1 (Latin-1) 字符集。

备注:为了方便起见,以下表格中,“实体名称”简称为“名称”,“实体编号”简称为“编号”

显示 名称 编号 显示 名称 编号 显示 名称 编号 显示 名称 编号 显示 名称 编号
&nbsp; &#160; ¡ &iexcl; &#161; ¢ &cent; &#162; £ &pound; &#163; ¤ &curren; &#164;
¥ &yen; &#165; ¦ &brvbar; &#166; § &sect; &#167; ¨ &uml; &#168; © &copy; &#169;
ª &ordf; &#170; « &laquo; &#171; ¬ &not; &#172; &shy; &#173; ® &reg; &#174;
¯ &macr; &#175; ° &deg; &#176; ± &plusmn; &#177; ² &sup2; &#178; ³ &sup3; &#179;
´ &acute; &#180; µ &micro; &#181; &para; &#182; · &middot; &#183; ¸ &cedil; &#184;
¹ &sup1; &#185; º &ordm; &#186; » &raquo; &#187; ¼ &frac14; &#188; ½ &frac12; &#189;
¾ &frac34; &#190; ¿ &iquest; &#191; À &Agrave; &#192; Á &Aacute; &#193; Â &Acirc; &#194;
à &Atilde; &#195; Ä &Auml; &#196; Å &Aring; &#197; Æ &AElig; &#198; Ç &Ccedil; &#199;
È &Egrave; &#200; É &Eacute; &#201; Ê &Ecirc; &#202; Ë &Euml; &#203; Ì &Igrave; &#204;
Í &Iacute; &#205; Î &Icirc; &#206; Ï &Iuml; &#207; Ð &ETH; &#208; Ñ &Ntilde; &#209;
Ò &Ograve; &#210; Ó &Oacute; &#211; Ô &Ocirc; &#212; Õ &Otilde; &#213; Ö &Ouml; &#214;
× &times; &#215; Ø &Oslash; &#216; Ù &Ugrave; &#217; Ú &Uacute; &#218; Û &Ucirc; &#219;
Ü &Uuml; &#220; Ý &Yacute; &#221; Þ &THORN; &#222; ß &szlig; &#223; à &agrave; &#224;
á &aacute; &#225; â &acirc; &#226; ã &atilde; &#227; ä &auml; &#228; å &aring; &#229;
æ &aelig; &#230; ç &ccedil; &#231; è &egrave; &#232; é &eacute; &#233; ê &ecirc; &#234;
ë &euml; &#235; ì &igrave; &#236; í &iacute; &#237; î &icirc; &#238; ï &iuml; &#239;
ð &eth; &#240; ñ &ntilde; &#241; ò &ograve; &#242; ó &oacute; &#243; ô &ocirc; &#244;
õ &otilde; &#245; ö &ouml; &#246; ÷ &divide; &#247; ø &oslash; &#248; ù &ugrave; &#249;
ú &uacute; &#250; û &ucirc; &#251; ü &uuml; &#252; ý &yacute; &#253; þ &thorn; &#254;
ÿ &yuml; &#255;

 

数学和希腊字母标志
symbols, mathematical symbols, and Greek letters

显示 名称 编号 显示 名称 编号 显示 名称 编号 显示 名称 编号 显示 名称
ƒ &fnof; &#402; Α &Alpha; &#913; Β &Beta; &#914; Γ &Gamma; &#915; Δ &Delta; &#916;
Ε &Epsilon; &#917; Ζ &Zeta; &#918; Η &Eta; &#919; Θ &Theta; &#920; Ι &Iota; &#921;
Κ &Kappa; &#922; Λ &Lambda; &#923; Μ &Mu; &#924; Ν &Nu; &#925; Ξ &Xi; &#926;
Ο &Omicron; &#927; Π &Pi; &#928; Ρ &Rho; &#929; Σ &Sigma; &#931; Τ &Tau; &#932;
Υ &Upsilon; &#933; Φ &Phi; &#934; Χ &Chi; &#935; Ψ &Psi; &#936; Ω &Omega; &#937;
α &alpha; &#945; β &beta; &#946; γ &gamma; &#947; δ &delta; &#948; ε &epsilon; &#949;
ζ &zeta; &#950; η &eta; &#951; θ &theta; &#952; ι &iota; &#953; κ &kappa; &#954;
λ &lambda; &#955; μ &mu; &#956; ν &nu; &#957; ξ &xi; &#958; ο &omicron; &#959;
π &pi; &#960; ρ &rho; &#961; ς &sigmaf; &#962; σ &sigma; &#963; τ &tau; &#964;
υ &upsilon; &#965; φ &phi; &#966; χ &chi; &#967; ψ &psi; &#968; ω &omega; &#969;
? &thetasym; &#977; ? &upsih; &#978; ? &piv; &#982; &bull; &#8226; &hellip; &#8230;
&prime; &#8242; &Prime; &#8243; &oline; &#8254; &frasl; &#8260; &weierp; &#8472;
&image; &#8465; &real; &#8476; &trade; &#8482; &alefsym; &#8501; &larr; &#8592;
&uarr; &#8593; &rarr; &#8594; &darr; &#8595; &harr; &#8596; &crarr; &#8629;
&lArr; &#8656; &uArr; &#8657; &rArr; &#8658; &dArr; &#8659; &hArr; &#8660;
&forall; &#8704; &part; &#8706; &exist; &#8707; &empty; &#8709; &nabla; &#8711;
&isin; &#8712; &notin; &#8713; &ni; &#8715; &prod; &#8719; &sum; &#8721;
&minus; &#8722; &lowast; &#8727; &radic; &#8730; &prop; &#8733; &infin; &#8734;
&ang; &#8736; &and; &#8743; &or; &#8744; &cap; &#8745; &cup; &#8746;
&int; &#8747; &there4; &#8756; &sim; &#8764; &cong; &#8773; &asymp; &#8776;
&ne; &#8800; &equiv; &#8801; &le; &#8804; &ge; &#8805; &sub; &#8834;
&sup; &#8835; &nsub; &#8836; &sube; &#8838; &supe; &#8839; &oplus; &#8853;
&otimes; &#8855; &perp; &#8869; &sdot; &#8901; ? &lceil; &#8968; ? &rceil; &#8969;
? &lfloor; &#8970; ? &rfloor; &#8971; ? &lang; &#9001; ? &rang; &#9002; &loz; &#9674;
&spades; &#9824; &clubs; &#9827; &hearts; &#9829; &diams; &#9830;

 

重要的国际标记
markup-significant and internationalization characters

显示 名称 编号 显示 名称 编号 显示 名称 编号 显示 名称 编号 显示 名称
&quot; &#34; & &amp; &#38; < &lt; &#60; > &gt; &#62; Π&OElig; &#338;
œ &oelig; &#339; Š &Scaron; &#352; š &scaron; &#353; Ÿ &Yuml; &#376; ˆ &circ; &#710;
˜ &tilde; &#732; &ensp; &#8194; &emsp; &#8195; &thinsp; &#8201; &zwnj; &#8204;
&zwj; &#8205; &lrm; &#8206; &rlm; &#8207; &ndash; &#8211; &mdash; &#8212;
&lsquo; &#8216; &rsquo; &#8217; &sbquo; &#8218; &ldquo; &#8220; &rdquo; &#8221;
&bdquo; &#8222; &dagger; &#8224; &Dagger; &#8225; &permil; &#8240; &lsaquo; &#8249;
&rsaquo; &#8250; &euro; &#8364;
  • html escape/unescape的实现原理

实现原理很简单,只要把string中存在的上述表中的所有文字都替换为相应的符号即可。

  • apache commons lang里StringEscapeUtils及Entities的实现

相面已经给出部分代码,通过下面的代码能清楚的了解到每个entity所包含的字符。entiries类实现了几个map,分别保存int,binary等待。

/**
*

* The set of entities supported by standard XML.
*

*/
public static final Entities XML;

/**
*

* The set of entities supported by HTML 3.2.
*

*/
public static final Entities HTML32;

/**
*

* The set of entities supported by HTML 4.0.
*

*/
public static final Entities HTML40;

static {
Entities xml = new Entities();
xml.addEntities(BASIC_ARRAY);
xml.addEntities(APOS_ARRAY);
XML = xml;
}

static {
Entities html32 = new Entities();
html32.addEntities(BASIC_ARRAY);
html32.addEntities(ISO8859_1_ARRAY);
HTML32 = html32;
}

static {
Entities html40 = new Entities();
fillWithHtml40Entities(html40);
HTML40 = html40;
}

/**
*

* Fills the specified entities instance with HTML 40 entities.
*

*
* @param entities
* the instance to be filled.
*/
static void fillWithHtml40Entities(Entities entities) {
entities.addEntities(BASIC_ARRAY);
entities.addEntities(ISO8859_1_ARRAY);
entities.addEntities(HTML40_ARRAY);
}

下面查看escape的具体操作。

public void escape(Writer writer, String str) throws IOException {
int len = str.length();
for (int i = 0; i < len; i++) { char c = str.charAt(i);
String entityName = this.entityName(c);
if (entityName == null) {
if (c > 0x7F) {  //通过这里可以看得到大于7f的也即扩展ascii码需要编码
writer.write("&#");
writer.write(Integer.toString(c, 10));
writer.write(';');
} else {
writer.write(c);
}
} else {

//其他已定义过的entity则直接替换
writer.write('&');
writer.write(entityName);
writer.write(';');
}
}
}

下面unescape的代码就给读者分析了。

public void unescape(Writer writer, String str) throws IOException {
int firstAmp = str.indexOf('&');
if (firstAmp < 0) {
writer.write(str);
return;
} else {
doUnescape(writer, str, firstAmp);
}
}
private void doUnescape(Writer writer, String str, int firstAmp) throws IOException {
writer.write(str, 0, firstAmp);
int len = str.length();
for (int i = firstAmp; i < len; i++) {
char c = str.charAt(i);
if (c == '&') {
int nextIdx = i + 1;
int semiColonIdx = str.indexOf(';', nextIdx);
if (semiColonIdx == -1) {
writer.write(c);
continue;
}
int amphersandIdx = str.indexOf('&', i + 1);
if (amphersandIdx != -1 && amphersandIdx < semiColonIdx) { // Then the text looks like &...&...; writer.write(c); continue; } String entityContent = str.substring(nextIdx, semiColonIdx); int entityValue = -1; int entityContentLen = entityContent.length(); if (entityContentLen > 0) {
if (entityContent.charAt(0) == '#') { // escaped value content is an integer (decimal or
// hexidecimal)
if (entityContentLen > 1) {
char isHexChar = entityContent.charAt(1);
try {
switch (isHexChar) {
case 'X' :
case 'x' : {
entityValue = Integer.parseInt(entityContent.substring(2), 16);
break;
}
default : {
entityValue = Integer.parseInt(entityContent.substring(1), 10);
}
}
if (entityValue > 0xFFFF) {
entityValue = -1;
}
} catch (NumberFormatException e) {
entityValue = -1;
}
}
} else { // escaped value content is an entity name
entityValue = this.entityValue(entityContent);
}
}

if (entityValue == -1) {
writer.write(‘&’);
writer.write(entityContent);
writer.write(‘;’);
} else {
writer.write(entityValue);
}
i = semiColonIdx; // move index up to the semi-colon
} else {
writer.write(c);
}
}
}

  • apache commons lang的下载

http://archive.apache.org/dist/commons/lang/ 这里可以下载到二进制的或者代码。

用maven的同学可以查看

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.1</version>
</dependency>

发表评论

电子邮件地址不会被公开。 必填项已用 * 标注

您可以使用这些 HTML 标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>