HTML エンティティ変換

テキストを HTML の中で安全になるようエスケープし、名前付き・数値の実体参照を元の文字に戻します。

テキスト
エンコード後

ここに結果が表示されます

このツールの役割

HTML には、テキストとして意図した小なり記号と、タグを開く小なり記号を区別する術がありません。この言語はそれをエンティティで解決します: マークアップとして読まれずに文字を表す、短いエスケープの並びです。このツールは両方向に変換します — 素のテキストをそのエスケープ形式に、そしてエスケープされた HTML をそれが表す文字に戻します。

どちらの向きも完全にブラウザ内で動きます。エンティティのデコーダーに人が貼り付けるテキストは、たいていスクレイピングしたページ・顧客のメール・意味を読み取ろうとしているデータベースの列なので、これはほとんどのツールより重要です。

重要な 5 つの文字

何千ものエンティティが存在しますが、テキストを安全にするのに必要なのはほんの一握りです。ここでのエンコードは正確に 5 つの文字を置き換え、それ以外はすべて読めるまま残します:

  • アンパサンドは & になります — これを最初に。さもないと他のすべての置換自体が再びエンティティとして読まれます。
  • 小なり記号は < になります — タグを始めうる文字です。
  • 大なり記号は > になります — 単独ではそれほど危険ではありませんが、対称性のため、また不注意なパーサーを生き延びるためにエスケープします。
  • 二重引用符は " になります — 二重引用符で書かれた属性値の中で必要です。
  • アポストロフィは ' になります — 単一引用符で書かれた属性値の中で必要です。

最後のものは意図的に数値で書かれています。' という名前もありますが、これは XML 由来で HTML 4 は決して定義しなかったので、古いパーサーは文字どおりのテキストとして通し、エスケープが黙って失敗します。数値形式は常にどこでも動いてきたので、まともなエスケープライブラリはそれを出します。

名前・10 進数・16 進数

どの文字も 3 通りに書け、デコードはそのすべてを受け付けます。em ダッシュがよい例です:

named     —      読める形式。ただし名前を持つ文字だけ
decimal   —      10 進数でのコードポイント
hex       —     同じコードポイントを 16 進数で。Unicode の一覧表が使う記法

このツールはデコード時に HTML 4 集合の 255 の名前を認識します — Latin-1 の文字、ギリシャ文字、矢印、数学記号、活字の約物で、それらだけで本物のテキストに現れるほぼすべてを覆います。HTML 5 はさらに約 2200 を定義しますが、ほとんどすべてが難解な数学記号です。その表を抱えると、ほとんどの文書が決して使わない名前と引き換えに、すべてのページ読み込みに数十キロバイトを加えることになります。集合外の名前は落とさず報告されるので、代償は警告であって、決して誤った答えではありません。

エンコードは逆向きで、意図的に素のままです: 上の 5 つの文字には名前を、それ以外すべてには 10 進数を使います。文字自体が UTF-8 文書で申し分なく有効なとき、それが … や ’ に変えられることはありません。

エスケープは 1 つの規則ではなく 4 つ

エンティティのエスケープをインジェクションへの答えと扱いたくなり、要素の内容の中では本当にそうです。しかし HTML は実は互いに入れ子になった 4 つの言語で、それぞれ独自の規則を持ちます。エンティティのエスケープは、このうち最初の 2 つの場所では正しく、残りでは役に立ちません:

  • 要素の内容 — タグ間のテキスト。エンティティのエスケープはまさに正しいです。
  • 引用符付きの属性値。属性が本当に引用符付きであれば、エンティティのエスケープは正しいです。引用符がなければ、値の中の空白が属性を終わらせ、エスケープは何ももたらしません。
  • スクリプトブロックの中。エンティティではなく JavaScript の文字列エスケープが当てはまります — ブラウザはそこでエンティティをデコードしないので、エスケープした引用符は文字どおりの文字 " として届きます。
  • href や src のような URL 属性。エンティティのエスケープは javascript: URL を止めません。危険はスキームにあり、エンティティが置き換えるどの文字にもないからです。

実務上の規則: テキストが文書に挿入される地点で、それが着地するまさにその文脈の規則を使ってエスケープすること — 後でどこでも効くよう願って、早く一度だけ、ではありません。

なぜ時々 & を見るのか

これはエンティティのデコーダーに手を伸ばす最もよくある理由です。テキストがエスケープされ、それからもう一度エスケープされた — たいていは一度アプリケーションのコードで、もう一度、出力を既にエスケープするテンプレートエンジンやフレームワークで、です:

original     Fish & Chips
escaped      Fish & Chips        表示: Fish & Chips
escaped x2   Fish & Chips    表示: Fish & Chips

デコードはちょうど 1 層を取り除くので、一度動かせばどの場合にいるかが分かります。出力にまだエンティティが含まれていれば、層が複数あったのです。直し方はほぼ決して表示時にエンティティを剥がすことではなく — 重複するエスケープの手順を見つけて取り除くことです。同じバグが保存されたデータを黙って壊しているからです。

非 ASCII と、そのための選択肢

UTF-8 で配信されるページは、アクセント付き文字・ヘブライ語・アラビア語・中国語・絵文字にエンティティを必要としません。それらの文字はそのままで有効で、読めるまま残すことが、ソースを読みやすく、ファイルを小さく保ちます。ここではそれが既定です。

この選択肢が存在するのは、一部の宛先が今も素の ASCII を要求するからです: 古いメールのテンプレート、127 を超えるバイトを壊すシステム、あるいは誰もエンコードを変えたがらないデータベースの列です。オンにすると、そうした文字を 10 進数の参照で書きます — é は é、א は א になります。

絵文字は一言添える価値があります。絵文字はそのコードポイント全体に対して 1 つの参照として書かれます。例えば 🙂 で、決して 2 つの半分としてではありません。JSON エスケープツールを使ったことがあれば、これはそこで起きることの逆です。あちらでは形式が絵文字を 2 つの \u エスケープに分けることを特に要求します。同じ文字、2 つの正しい答え。2 つの形式が異なる単位でエスケープを定義するからです。

参照をデコードできないとき

ここでのデコードは決して失敗せず、何も削除しません。解決できない参照は見つかったとおりに残され、その行と列とともに出力の上に一覧されます。3 つのことが報告されます:

  • &nbps; のような不明な名前 — ほぼ常に   の打ち間違いです。これは対処する価値のある警告です: 内容から空白が欠けているのに誰も気づかなかった、という意味だからです。
  • � や Unicode 範囲を超えた値のような、文字でない数値。デコードする先がないので、テキストのまま残ります。
  • 128 から 159 の間の数値。下記参照。

単独のアンパサンドはまったく報告されません。HTML では R&D や Q&A はふつうのテキストで、はぐれたアンパサンドをすべてエラー扱いすると、重要な警告が散文の雑音に埋もれてしまいます。

128 から 159 の範囲は本物の奇妙さです。それらの数値は誰も書くつもりのない目に見えない制御文字を指します。文書が Windows-1252 で作られたために現れるもので、そこでは同じ数値が丸い引用符・ダッシュ・ユーロ記号です。ブラウザはまさにその理由でそれらを黙って Windows-1252 として読み、このツールもその振る舞いに合わせるので、結果はページが実際に表示するものと等しくなります — ただし警告でそう伝えます。頼んでいない黙った置き換えは、うるさい置き換えより悪いからです。

よくある質問

これら 5 つの文字をエスケープすれば XSS を止めるのに十分ですか?
要素の内容と引用符付きの属性値の中では、はい — まさにそのためのものです。スクリプトやスタイルブロックの中、引用符のない属性の中、href のような URL 属性の中では十分ではなく、それぞれ独自のエスケープ規則が必要です。エスケープはテキストの性質ではなく、テキストが着地する場所の性質です。
アポストロフィが ' ではなく ' と符号化されるのはなぜですか?
' は HTML 4 が決して定義しなかった XML エンティティだからです。HTML 5 より前のパーサーはそれを文字どおりのテキストとして残すので、エスケープしたつもりのアポストロフィがそうなっていません。数値形式はどのパーサーでも動くので、安全な既定です。
私のページがアンパサンドの代わりに & を表示します。何が起きたのですか?
テキストが 2 回エスケープされたのです。ここでデコードしてください: 1 回で & が & になり、余分な層を確かめられます。テキストではなくパイプラインを直してください — たいてい、あなたのコードが、テンプレートエンジンが既にエスケープしていた出力をエスケープしています。
ヘブライ語・アラビア語・絵文字を符号化する必要がありますか?
UTF-8 で配信される現代のページには不要です。そのままで有効です。非 ASCII の選択肢は、古いメールのテンプレートのように下流の何かが素の ASCII を要求するときにだけオンにしてください。そのとき各絵文字は単一の数値参照として書かれます。
“ をきちんとデコードしたのに、ツールがそれを警告するのはなぜですか?
147 が、あなたが見る引用符ではなく、目に見えない制御文字を指すからです。それを使う文書は Windows-1252 で書かれており、そこでは 147 が丸い引用符です — ブラウザはそう読み、このツールもそうします。警告は置き換えが起きたことを伝えるので、ソースのエンコードが自分で直せるものなら直せます。
私のテキストはどこかに送られますか?
いいえ。エンコードもデコードも完全にブラウザ内で動きます。貼り付けた内容が端末の外に出ることはありません。