NCR

在html中总会出现一些以&#x开头的字符串,但是在浏览器中就会显示出正常的我们所熟知的字符,使用decode/unescape/decodeURI解码均无效,因为这不是编码

疑问那么为什么会有这些字符出现呢?

#1# 那要从字符编码说起......

读写文字是人与动物的最大区别,不同的种族发明了不同的语言文字,对这些文字进行二进制表示是计算机领域必须要解决的问题。文本处理在计算机程序中占有相当大的比例,尤其是在web程序中,几乎大部分程序逻辑都是为了最终输出处理过的文本。目前世界上存在有很多种字符编码标准,各个标准并不完全兼容,甚至完全不同,从而导致了“乱码”这个让很多程序员都胆战心惊的东西。

尽管目前统一的编码规范UNICODE大行其道,被越来越广泛地使用,然而尚未达到完全统治字符编码界的水平。

#2# 再说一下元字符:

在标记语言中,都会定义一些被称为“元字符”的特殊字符,这些字符具有特殊的作用,不再具有原来字面上的意义。我们以HTML为例,小于号(<)就是一个最常用的元字符,它表示一个标签的开始,而不再具有“小于号”这个字面意义。

那么想要这些元字符的字面含义该怎么办呢?
解决方法就是:用元字符引导字符序列来表示元字符的字面含义。例如在HTML中元字符<的字面值就是用如下序列表示。

&lt;

像“<”和“>”这类符号已经用来表示HTML标签,因此就不能直接当作文本中的符号来使用。为了在HTML文档中使用这些符号,就需要定义它的转义字符串。当解释程序遇到这类字符串时就把它解释为真实的字符。在输入转义字符串时,要严格遵守字母大小写的规则。转义字符串(Escape Sequence)也称字符实体(Character Entity)。

再比如说,HTML会自动截去多余的空格。不管你加多少空格,都被看做一个空格。比如你在两个字之间加了10个空格,HTML会截去9个空格,只保留一个。为了在网页中增加空格,你可以使用&nbsp;表示空格。下表中表示就是最常用的一些字符实体。


#3# 除此以外还有一些不可编码字符......

很多的字符编码标准并不能涵盖所有的字符,例如ASCII编码只包含128个字符,根本不能表示英文之外的其他任何语言文字。这样就会导致一个问题:想要在ASCII编码的文件中记录汉字怎么办?

解决方法就是:用元字符引导的可编码字符序列来表示不可编码字符。解码程序能够识别这个格式的字符序列,然后把它转换成原本的不可编码字符。例如,汉字“中”在ASCII编码的HTML文件中可以使用如下序列表示。

&#20013;

这个序列只含有可以用ASCII编码的字符。浏览器在遇到这个序列时,自动转换为汉字“中”并正确显示出来,当然前提是浏览器自身具有显示汉字的能力。

前面提到的元字符引导的可编码字符序列到底是如何规定的呢?目前有两种方案:

1>一种就是在html中常用的被称为实体的规范

例如上面提到的

&lt;

这种规范中定义了很多特定的字符序列,然而总归是非常有限的,主要是为了表示元字符的字面值。对于广大的汉字仍不能表示。

2>另一种就是被称为NCR的规范

在NCR中,使用字符的UNICODE代码点数值的十进制或十六进制表示字符串来代表这个字符。例如上面例子中

&#20013;

其中的20013就是汉字“中”在UNICODE编码中的代码点。当然也可以使用16进制来表示,如下

&#x4E2D;

这种规范看似简单,却非常强大,因为它可以表示任意的字符,只用UNICODE编码中定义了这个字符,它就可以轻松表示。存在的问题是,很少有人能记住一个字符的UNICODE代码点,需要去查表才行。

尽然NCR能表示任何字符,当然也能够表示元字符的字面值了,例如前面的

&lt;

也可以使用

&#60;

来表示。

总的来说,形如

&name;
&#dddd;
&#xhhhh;

的一串字符是 HTML、XML 等 SGML 类语言的转义序列(escape sequence)。它们不是「编码」。以 HTML 为例,这三种转义序列都称作 character reference:第一种是 character entity reference,后接预先定义的 entity 名称,而 entity 声明了自身指代的字符。
后两种是 numeric character reference(NCR),数字取值为目标字符的 Unicode code point;以「&#」开头的后接十进制数字,以「&#x」开头的后接十六进制数字。

从 HTML 4 开始,NCR 以 Unicode 为准,与文档编码无关。「中国」二字分别是 Unicode 字符 U+4E2D 和 U+56FD,十六进制表示的 code point 数值「4E2D」和「56FD」就是十进制的「20013」和「22269」。所以

我给加了空格,不然网页会自动渲染成文字...
&#x 4e2d;&#x 56fd;
&# 20013;&# 22269;

这两种 NCR 写法都会在显示时转换为「中国」二字。NCR 可以用于转义任何 Unicode 字符,而 character entity reference 很受限,参见 HTML 4 和 HTML5 中已有定义的字符列表:

Character entity references in HTML 4

Character entity references in HTML5

#4# 你不知道的unicode

UNICODE编码涵盖了世界上已知的所有字符,除了各种语言的文字外,还包含了很多符号,标记。下面给出几个小例子。

  • &#x2605; 对应 ★
  • &#x2694; 对应 ⚔
  • &#x2695; 对应 ⚕
  • &#x2713; 对应 ✓

另外,UNICODE中还定义了一些组合字符,它们本身不能单独存在,必须作用于前面的基本字符上,例如常见的重音符号。

  • A&#x030E; 对应 A̎

广大的90后小朋友网络上广泛使用的火星文就是把各种UNICODE字符按照特定的规则组合起来的。

如下序列:

&#12389;&#28779;&#9734;&#25909;&#257;

显示效果:

づ火☆攵ā

疑问但是有时候我们在解析html的时候需要对它进行反转义,所以查找了一些方法:

1>自然是自己编程实现,但是总是不是那么完整

2>借用第三方包,如果是java,可以使用apache工具包common-lang中有一个很有用的处理字符串的工具类StringEscapeUtils,里面有很多静态的方法,可以直接通过类来调用。

String str1 = StringEscapeUtils.unescapeHtml4("Log in to your &#x50;&#x61;&#x79;&#x50;&#x61;&#x6C; Account");
System.out.println(str1);

就可以得到反转义结果:

Log in to your PayPal Account

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值