HTML 实体编解码在浏览器本地把字符与 HTML 实体互相转换。转义解决的是同一个问题:怎么让浏览器把一段文本当文本读,而不是当标签读。
| 形式 | 写法 | 适用 |
|---|---|---|
| 命名实体 | © — | HTML 文档,可读性最好 |
| 十进制 | © — | XML / SVG / RSS,任何解析器都认 |
| 十六进制 | © — | 与 Unicode 码点一一对应,便于查表 |
XML 只认五个命名实体(amp lt gt quot apos),其余名字在 XML 解析器里会直接报错。生成 XML 类文档时选数字形式。
& < > " '。把用户输入放进 HTML 就用这个,中文原样保留、源码可读—、© 等。给只认 ASCII 的老管道用= / 都转。体积翻倍,只在极保守的模板注入场景下用HTML 实体只对 HTML 解析器有效。同一段数据放进 <script> 里要用 JS 字符串转义,放进 href/src 要用 URL 编码,放进 CSS 要用 CSS 转义。搞错上下文,转义了也照样能被注入。
编解码全部在浏览器内完成,不上传任何内容。
把用户输入放进 HTML 正文或属性值,转义 & < > " ' 这五个就够了,这也是工具的默认「仅特殊字符」模式。& 必须第一个转,否则后面转出来的实体会被二次破坏。要放进只认 ASCII 的管道(老邮件网关、某些打印系统)才需要「含非 ASCII」。「尽可能多」连 = / 都转,只在极保守的模板注入场景用得上,平时开着只会让源码难读、体积变大。
在 HTML 里用命名实体最可读,跨解析器用数字实体最安全。命名实体(©、—)是 HTML 规范定义的名字表,XML 解析器只认 & < > " ' 五个,其余名字一律报错。所以生成 XML、SVG、RSS、XHTML 时选十进制或十六进制。十六进制的好处是和 Unicode 码点表一一对应,© 一眼能查到是 U+00A9。
能,但必须转对位置。转义是防 XSS 的核心手段,前提是按上下文选转义规则:放进 HTML 正文,转义这五个字符就够;放进属性值,属性必须用引号包起来(不然 onerror=x 无引号属性可以直接注入);放进 <script> 里的 JS 字符串,HTML 实体完全无效,要用 JS 转义;放进 URL 里要用 URL 编码而不是实体。一句话:实体转义解决的是"HTML 解析器怎么读这段文本",管不到 JS 和 URL 解析器。
解码出来看着像普通空格,复制到编辑器又不对?因为它不是普通空格。 是 U+00A0 不换行空格,看起来一样,但不会在这里折行,也不会被大多数 trim() 和正则 \s 之外的处理当空格。从网页复制文本到代码里经常带进这个字符,表现是"看着没问题但字符串比较永远不相等"。工具解码后原样保留 U+00A0——想确认的话,把结果再编码一次,它会变回 。
¬real; 解码成了 ¬real;?这是 HTML5 规范的历史包袱,不是 bug。少数早期实体(¬、&、< 等)允许不带分号就生效,所以解析器看到 ¬ 就先把它吃掉了,剩下 real; 原样保留。浏览器的行为完全一致——可以自己在页面里试。这也是为什么写实体时永远要带分号。
不会。编解码由 html-entities 库在浏览器本地完成,输入内容不出机器,适合处理带 token、内部接口路径的片段。localStorage 里只存三个选项(范围、形式、是否实时),不存正文。