HTML をエスケープ・アンエスケープする方法
- エスケープ か アンエスケープ を選びます。
- エスケープする場合は、エスケープ対象 で何をエスケープするか選びます。
- & < > " ’ のみ:ページやテンプレートに貼り付ける HTML 向け。
- 非 ASCII 文字もすべて:UTF-8 を安全に扱えないページ、メール、システム向け。
- すべての文字:テキスト全体をエンコードします。パーサーのテスト用です。
- 形式 を選びます。名前付き(é)、10進数(é)、16進数(é) です。名前付きでは、一般的な名前のない文字は10進数になります。テキストを要素の内容にしか入れないなら、引用符をエスケープ のチェックを外してください。
- 出力をコピー します。入れ替え で結果を反対側に移し、往復して元に戻るか確かめられます。
アンエスケープにはブラウザの HTML パーサーを使うので、HTML5 にある 2,000 以上の名前付き文字参照すべてと、10進数・16進数の文字参照に対応しています。入力が HTML としてレンダリングされることはありません。
よく使うエンティティ
| 文字 | 名前付き | 10進数 | 16進数 |
|---|---|---|---|
& | & | & | & |
< | < | < | < |
> | > | > | > |
" | " | " | " |
' | '(HTML5) | ' | ' |
| ノーブレークスペース | |   |   |
é | é | é | é |
— | — | — | — |
€ | € | € | € |
© | © | © | © |
😀 | なし | 😀 | 😀 |
数値文字参照は Unicode のコードポイントを使います。絵文字は UTF-8 では 4 バイトですが、参照は 1 つで済みます。
エスケープとデコードの落とし穴
&を最初にエスケープする。<を<に置き換えてから&を&に置き換えると、&lt;になってしまいます。自作のエスケープ処理では、&をほかより先に処理してください。- エンコードしていない
&が記号に化けることがある。 HTML はセミコロンのない古いエンティティの一部を今でも認識するので、テキスト?id=1©=2¶=3は?id=1©=2¶=3と表示されます。URL の中も含め、アンパサンドはすべて&と書いてください。 - 二重エスケープ は、ページ上に
&lt;b&gt;として現れます。1 回アンエスケープしてから、どの層で 2 回エスケープしているかを探してください。 は空白ではない。 デコードすると U+00A0 になり、見た目は空白でも、言語によっては文字列の比較やtrim()で一致しません。- エンティティは URL エンコードではない。 リンクの中で、
&は HTML ソース上でクエリパラメーターを区切るものですが、%26は値の中の文字としてのアンパサンドです。後者は URL エンコーダー で扱えます。
コードでのエスケープとアンエスケープ
import html
html.escape('5 > 3 & "quotes"') # '5 > 3 & "quotes"'
html.unescape("Café — ©") # 'Café — ©'
const escapeHtml = s => s.replace(/&/g, "&").replace(/</g, "<")
.replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
const unescapeHtml = s =>
new DOMParser().parseFromString(s, "text/html").documentElement.textContent;
Python の html.escape はデフォルトで引用符もエスケープし、' を ' と書きます。PHP では htmlspecialchars() が定番で、PHP 8.1 以降はデフォルトで両方の引用符をエスケープします。DOMParser はパースしたドキュメント内のスクリプトを実行しないので、ブラウザで安全にデコードする方法として使えます。JavaScript での文字列の扱いについては JavaScript のページ をご覧ください。
エンティティ、Base64、Data URI
HTML エンティティと Base64 は、解決する問題が違います。エンティティは HTML ソースの中で文字を安全にするもので、Base64 はバイト列をテキストにして、ファイル丸ごとを属性に収めるものです。HTML 文書全体を data: URI や JSON のフィールドに埋め込むなら、文字を 1 つずつエスケープするのではなく、HTML を Base64 に変換 でエンコードしてください。
よくある質問
HTML でエスケープが必要な文字はどれですか?
テキストの中では & と <、それに慣例として > です。属性値の中では、値を囲んでいる引用符(" または ')も必要です。アクセント付きの文字や絵文字を含め、それ以外はすべて UTF-8 のページならそのままで構いません。
' と ' の違いは何ですか?
どちらもアポストロフィを表します。' は HTML5 と XML で定義されていますが HTML 4 にはなかったため、どのパーサーやメールクライアントでも通じるのは ' のほうです。このツールのエスケープでは ' を使います。
ページに &amp; と表示されるのはなぜですか?
テキストが 2 回エスケープされています。& が & になり、2 回目でそれが &amp; になりました。ここで 1 回アンエスケープすれば意図したテキストに戻ります。余分なエスケープの処理も取り除いてください。たいていは、エスケープ済みの値をテンプレートエンジンがさらにエスケープしています。
HTML エンティティでエスケープすれば XSS を防げますか?
HTML のテキストと、引用符で囲んだ属性値への注入は防げます。<script> ブロック、javascript: の URL、CSS、引用符のない属性の中では安全になりません。これらの文脈にはそれぞれ専用のエンコードが必要です。テンプレートエンジンの自動エスケープを優先して使ってください。