HTML エンティティ エンコード / デコード

HTML エンティティのエスケープと復元を行います。< > & " ' を名前付き参照に変換し、任意で非 ASCII 文字もすべてエンコード、名前付き / 数値参照のデコードにも対応。

HTML に安全に埋め込めるようテキストをエスケープし、エンティティを文字に戻します。 どちらの欄に入力してもその方向へ変換します。最小モードは正しさに関わる 5 文字だけをエスケープし、拡張モードは互換性を最大化するため非 ASCII 文字もすべてエンコードします。

よく使うエンティティ

文字 名前付き 数値参照
& &amp; &#38;
< &lt; &#60;
> &gt; &#62;
" &quot; &#34;
' &#39; &#39;
\u{00A0} &nbsp; &#160;
\u{00A9} &copy; &#169;
\u{20AC} &euro; &#8364;

HTML エンティティとエスケープの重要性

HTML を壊す 5 つの文字

HTML パーサーは < をタグの開始、& をエンティティ参照の開始として読みます。コンテンツにこれらが含まれていると、パーサーはそこをテキストとして扱わなくなります。エスケープとは、その文字を参照に置き換えることで、パーサーが元の字形に復元しつつ構造上の意味を一切与えないようにする処理です。

HTML で本当にエスケープが必要な文字は 5 つだけです。

  • &&amp;最初に置換すること。さもないと他のエスケープが二重になります
  • <&lt;
  • >&gt;
  • "&quot; — 二重引用符の属性値の中では必須
  • '&#39; — 一重引用符の属性値の中では必須

厳密には、要素のテキストでは &< だけで足ります。残りの 3 つはテキストが属性値に入りうる場合に効いてきますが、エスケープする時点で行き先を制御できることはまれなので、5 つすべてを処理するのが安全な習慣です。

名前付き・10 進・16 進の参照

同じ文字を 3 通りに書けます。ノーブレークスペースは &nbsp;&#160;&#xA0; のいずれでも表せます。名前付き参照が最も読みやすいものの、HTML5 の名前表は約 2,200 件あり、古いパーサーが知っているのははるかに少ないため、珍しい名前は移植性のリスクになります。数値参照は任意の Unicode コードポイントで使え、常に安全です。HTML5 では名前付き参照に末尾のセミコロンが必須です。&amp のような一部のレガシー名は後方互換のためセミコロンなしでも解析されますが、それに頼るのは事故のもとです。

エスケープはサニタイズではない

エスケープはクロスサイトスクリプティングを止める要です。<script> を含むユーザー入力が &lt;script&gt; にエスケープされれば、ブラウザは文字どおりのテキストを表示するだけで何も実行しません。ただし、エスケープは正しいコンテキストで行われて初めて機能します。<script> ブロック内、style 属性内、URL の中では HTML エスケープでは不十分で、それぞれ固有のエンコードが必要です。さらにエスケープは出力時に 1 回だけ適用します。入力時と出力時の両方でエスケープすると &amp;lt; が生まれ、画面に文字化けが出ます。

拡張モードが必要な場面

非 ASCII 文字のエスケープを求める現代仕様はありません。UTF-8 文書は é をそのまま含められますし、通常はそのほうが望ましい選択です。短く、読みやすく、検索もしやすくなります。拡張モードは、バイト列が非 ASCII を壊すチャネルを通らなければならない場合のためにあります。レガシーなメールテンプレート、古い CMS のフィールド、宣言エンコーディングが不明瞭な XML パイプライン、Latin-1 のままのビルド工程などです。エンコーディングを端から端まで制御できるなら最小モードのままで構いません。

ノーブレークスペースの罠

&nbsp; は U+00A0 であり、通常の空白 U+0020 とは別の文字です。改行を防ぎ、連続する空白の圧縮も抑止するため、WYSIWYG エディタが多用します。見た目が同一なので、文字列比較、エンジンによっては \s で書いた正規表現、CSV の取り込みを静かに壊します。値が正しく見えるのにどうしても一致しないときは、紛れ込んだノーブレークスペースを疑ってください。

オープンソースに関する注記:単純な文字列およびコードポイント演算で実装しています。サードパーティライブラリは使用していません。

よくある質問

大なり記号もエスケープが必要ですか?
厳密には不要です。テキスト中の単独の > は曖昧さがなく問題なく解析されます。慣習としてエスケープするのは、コストがゼロで、生成されたマークアップの混乱を避けられるためです。出力をブラウザより厳格なツールが後段で処理する場合はとくに有効です。
なぜ & を最初にエスケープするのですか?
他のエスケープ列がすべてアンパサンドで始まるからです。& より先に < を &lt; に置換すると、次の処理でそのアンパサンドが &amp; になり、ページに &amp;lt; と出てしまいます。
エスケープだけで XSS を防げますか?
HTML のテキストと属性のコンテキストに限り、かつ出力時に適用した場合だけです。JavaScript・CSS・URL に差し込まれる内容には、その言語のエスケープ規則が必要です。エスケープは防御の 1 層であって全体ではありません。
名前付きと数値参照はどちらを使うべき?
数値参照は普遍的にサポートされ、任意のコードポイントで使えます。名前付きは、誰もが知っている数個については読みやすいです。実務では、基本の 5 文字は名前付き、珍しい文字は数値参照が無難です。
アクセント付き文字はエンコードすべき?
UTF-8 文書では不要で、現代の Web コンテンツはほぼ UTF-8 です。そのまま書いてください。パイプラインのどこかが非 ASCII バイトを確実に運べない場合だけ拡張モードを使います。
&nbsp; と通常の空白の違いは?
ノーブレークスペースはコードポイント U+00A0 です。見た目は同じですが折り返しを防ぎ、隣接する空白と圧縮されません。比較上も別の文字であり、微妙なバグの定番の原因になります。