极简工具箱

免费在线工具 · 本地计算 · 无需上传

HTML 实体编码:& < ' 什么时候必须转义

在页面上想显示一个 `

` 标签,结果它真的变成了一个 div;从数据库读出的内容里带着 `&lt;`,页面上就明晃晃显示着 `<`。HTML 实体是最基础也最容易搞错的一层。

广告位(百度联盟)

一、五个必须转义的字符

字符实体为什么必须转
&&amp;amp;它是实体本身的起始符,不转义会导致后续解析错乱
<&amp;lt;会被当成标签开始
>&amp;gt;严格说可省,但成对转义更安全
"&amp;quot;出现在属性值里会截断属性
'&amp;#39;单引号包裹的属性里会截断

其余字符(中文、emoji、常见符号)在 UTF-8 页面里可以直接写,不需要转义。把整段中文逐字转成 &#20013; 只会让文件变大、可读性变差。

二、命名实体 vs 数字实体

  • 命名实体:&amp;nbsp; &amp;copy; &amp;mdash;,好读,但 HTML 只预定义了很小一部分(约 2000 个,实际常用的几十个)。
  • 数字实体:&amp;#39;(十进制)或 &amp;#x27;(十六进制),任何 Unicode 字符都能表示。

XML 只认五个预定义实体(&amp;lt; &amp;gt; &amp;amp; &amp;quot; &amp;apos;),自定义命名实体在 XML 里会解析失败,跨格式输出时要改用数字实体。

三、转义顺序:& 必须第一个处理

这是最经典的 bug:

// 错误:先转 < 再转 &,会把刚生成的 &lt; 又转一遍
s.replace(/</g, '&lt;').replace(/&/g, '&amp;');
// "<" → "&amp;lt;"   ← 页面上显示 &lt;

// 正确:先 & 后其他
s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;')
 .replace(/"/g, '&quot;').replace(/'/g, '&#39;');

页面出现 &amp;lt; 或 &amp;amp;,九成是转义了两次(后端转一次、前端又转一次),或者顺序写反了。修复时不要在前端「反转义一次」了事,应该找到重复转义的那一层去掉。

四、不同上下文的规则不一样

  • HTML 文本节点:转 & < > 即可,引号可留。
  • 双引号属性值:必须转 ",' 可留。
  • 单引号属性值:必须转 '。
  • <script> 内部:HTML 转义无效,需要 JSON 序列化或专用转义(< 写成 \u003c),否则 </script> 会提前闭合标签。
  • <textarea> / <title>:只支持文本,标签不会生效,尖括号仍建议转义以免截断。
  • URL 参数:用 URL 编码,不是 HTML 实体。

一个常见误区是「只要做了 HTML 转义就安全」。实际上属性没加引号、或者把用户输入拼进 onclick、href="javascript:",转义了照样能被利用。

五、什么时候不要转义

  • 富文本编辑器产出的 HTML(本身就该是标签)——这时要做的是白名单过滤,不是转义。
  • 自己写死的模板片段。
  • JSON 响应体里的内容(JSON 有自己的转义规则,不是 HTML 实体)。

判断标准很简单:这段字符串是要「显示成文字」还是「当成结构解析」。前者转义,后者过滤。

六、快速自查

拿不准某段内容转义后是什么效果,用 HTML 实体编解码工具 双向对照;如果是从接口拿到的 JSON 里带一堆实体,先用 JSON 格式化 看清原始字符串,再判断该在哪一层处理。

小结

五个必转字符里 & 要最先处理;转义两次是 &amp;lt; 的唯一来源;<script> 内不能用 HTML 转义;富文本要过滤而不是转义。

本文相关工具(本地计算,无需上传)

更多使用教程