jQueryを使用してHTMLエンティティをデコードする方法は?


334

jQueryを使用して文字列内のHTMLエンティティをデコードするにはどうすればよいですか?


テクノロジー(jQuery)の時期尚早な選択は、セキュリティ問題のある答えを招きます。これは、stackoverflow.com / questions / 1912501 / …の複製として閉じたほうがよいでしょう。
Wladimir Palant

回答:


437

セキュリティ上の注意:この回答(以下の元の形式で保持される)を使用すると、アプリケーションにXSSの脆弱性が生じる可能があります。この答えは使用しないでください。この回答の脆弱性の説明についてはルカスカロの回答を読み、代わりにその回答またはマークアメリーの回答からのアプローチを使用してください。

実は、やってみて

var decoded = $("<div/>").html(encodedStr).text();

175
ではない、信頼できない入力でこれを行います。多くのブラウザは、ノードがDOMに接続されていなくても、画像を読み込んで関連イベントを発生させます。実行してみてください$("<div/>").html('<img src="http://www.google.com/images/logos/ps_logo2.png" onload=alert(1337)>')。FirefoxまたはSafariでは、アラートが発生します。
マイクサミュエル

@マイク、代わりに何を勧めますか?何を置き換えるのかわからない場合、.replace()の答えは役に立ちません...
ekkis '29

7
@ekkis、エンティティをデコードする前にタグを取り除く必要があります。 str.replace(/<\/?\w(?:[^"'>]|"[^"]*"|'[^']*')*>/g, "")または似たようなもの。
マイク・サミュエル

2
入力からほとんどのHTMLタグ(Mikeの好意による)を取り除く(私の意見では)より良い実装は、同様の質問の私の答えです。また、jQueryのオーバーヘッドがないため、他の環境に非常に適しています。
Robert K

6
@MichaelStumここでの編集により、Mike Samuelのコメントと次に高い投票の回答の両方が無効になり、実際にすべてのjQueryバージョンのXSS脆弱性修正せずに無効にしました(以下の回答で説明)。この回答にセキュリティ警告を追加することは合理的です(そうするつもりです)。セキュリティホールを実際に修正できなかったときに、このページの他のディスカッションを無意味なものにすることは間違いありません。
Mark Amery 2016

211

jQueryなし:

function decodeEntities(encodedString) {
  var textArea = document.createElement('textarea');
  textArea.innerHTML = encodedString;
  return textArea.value;
}

console.log(decodeEntities('1 &amp; 2')); // '1 & 2'

これは受け入れられた回答と同様に機能しますが、信頼できないユーザー入力で安全に使用できます。


同様のアプローチにおけるセキュリティの問題

マイク・サミュエルが指摘し、でこれを行う<div>代わりに、<textarea>信頼できないユーザの入力を持つことはあっても、XSSの脆弱性である<div>DOMに追加されることはありません。

function decodeEntities(encodedString) {
  var div = document.createElement('div');
  div.innerHTML = encodedString;
  return div.textContent;
}

// Shows an alert
decodeEntities('<img src="nonexistent_image" onerror="alert(1337)">')

ただし、の<textarea>コンテンツが許可されているHTML要素がないため、aに対してこの攻撃を行うことはできません<textarea>。その結果、「エンコードされた」文字列にまだ存在するHTMLタグは、ブラウザによって自動的にエンティティエンコードされます。

function decodeEntities(encodedString) {
    var textArea = document.createElement('textarea');
    textArea.innerHTML = encodedString;
    return textArea.value;
}

// Safe, and returns the correct answer
console.log(decodeEntities('<img src="nonexistent_image" onerror="alert(1337)">'))

警告:この使用してjQueryの行う.html().val()メソッドの代わりに使用する.innerHTML.value、jQueryのいくつかのバージョンの安全性の低いもある*を使用する場合でもtextarea。これは、古いバージョンのjQueryが渡される文字列に含まれるスクリプト意図的かつ明示的に評価するため.html()です。したがって、次のようなコードはjQuery 1.8のアラートを示しています。

//<!-- CDATA
// Shows alert
$("<textarea>")
.html("<script>alert(1337);</script>")
.text();

//-->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.2.3/jquery.min.js"></script>

* この脆弱性をキャッチしてくれたEru Penkmanに感謝します。


6
その値を抽出した後にテキストエリアを破壊するのは良い考えかもしれません:decodedString = textArea.value; textArea.remove(); return decodedString;
ヴェルナー

2
または、javascriptのバージョンが実際にremove()をサポートしている場合のみ:if ('remove' in Element.prototype) textArea.remove();
Werner

6
@Werner関数が終了するとすぐに、その関数への参照を保持する変数がなくなるため、ガベージコレクターによって自動的に削除されます。
user2428118 2017年

私はこれを.NETと組み合わせて、ボタンクリックのコードビハインドから使用しています。何らかの理由で、受け入れられた回答がポストバックを引き起こしました。この答えはなかったので、これが私にとって最良の答えです。ありがとう!
スナイラー2017

@Snailer $("<div />").html(string).text() は、提供された文字列内の任意のJavaScriptを実行します。これが問題の原因であったと思われます。承認された回答はこれに更新する必要があります。
jbowman

80

Mike Samuelが言ったように、安全でないため、jQuery.html()。text()を使用してHTMLエンティティをデコードしないでください。

代わりに、@ VyvITのコメントからMustache.jsdecodeEntitiesなどのテンプレートレンダラーを使用してください。

Underscore.jsユーティリティベルトライブラリにはメソッドescapeunescapeメソッドが付属していますが、ユーザー入力に対して安全ではありません。

_.escape(string)

_.unescape(文字列)


2
これは実際にはもっと多くの賛成投票に値します!間違いなく私の好ましい解決策。彼らはunescape今までにドキュメントに含まれています。
致命的なギター

5
_.unescape("&#39;")結果は「&#39;」のみ 単一引用符の代わりに。示すように、私が欠けているか、アンダースコアHTMLエンティティコードにエスケープしていませんが、何かがある:w3schools.com/tags/ref_entities.asp
ジェイソンAxelson

6
githubのバグは「修正しない」としてクローズされました。つまり、このソリューションは機能せず、機能しません。
Igor Chubin

3
あなたはアンダースコアのescapeそしてunescapeメソッドは...ユーザー入力に対して安全ではない」と言います。これはどういう意味ですか?それは私にはナンセンスのように聞こえますが、おそらく何かが足りないのです-明確にしていただけますか
マークアメリー2015

2
@VyvITを試しました_.unescape("&lt;img src=fake onerror=alert('boo!')&gt;")(Chrome / FF / IEで)。ただし、アラート表示されませんでした。コンソールで試してみただけでなく、JSファイルにも入れました。同じ結果。
Vivek Athalye 2017年

28

テキストとHTMLのメソッドを混同していると思います。この例を見てください。要素の内部HTMLをテキストとして使用すると、デコードされたHTMLタグ(2番目のボタン)が表示されます。しかし、それらをHTMLとして使用すると、HTML形式のビュー(最初のボタン)が表示されます。

<div id="myDiv">
    here is a <b>HTML</b> content.
</div>
<br />
<input value="Write as HTML" type="button" onclick="javascript:$('#resultDiv').html($('#myDiv').html());" />
&nbsp;&nbsp;
<input value="Write as Text" type="button" onclick="javascript:$('#resultDiv').text($('#myDiv').html());" />
<br /><br />
<div id="resultDiv">
    Results here !
</div>

最初のボタンの書き込み:これHTMLコンテンツです。

2番目のボタンの書き込み:これは<B> HTML </ B>コンテンツです。

ちなみに、jQueryプラグインで見つけたプラグイン-HTMLのエンコードとデコードを行うHTMLのデコードとエンコードを確認できます。


26

質問は「jQueryを使用する」によって制限されますが、ここでの最良の回答で提供されるjQueryコードは以下のことを実行することを理解するのに役立ちます...これはjQueryの有無にかかわらず機能します。

function decodeEntities(input) {
  var y = document.createElement('textarea');
  y.innerHTML = input;
  return y.value;
}

20

あなたは使用することができ、彼から入手できる、ライブラリをhttps://github.com/mathiasbynens/he

例:

console.log(he.decode("J&#246;rg &amp J&#xFC;rgen rocked to &amp; fro "));
// Logs "Jörg & Jürgen rocked to & fro"

は、ライブラリーの作成者に、このライブラリーをクライアントサイドのコードで使用して、ここや他の回答<textarea>提供されているハックを支持する理由があるかどうかについて質問しました。彼はいくつかの可能な正当化を提供しました:

  • node.jsサーバーサイドを使用している場合、HTMLエンコード/デコード用のライブラリを使用すると、クライアントサイドとサーバーサイドの両方で機能する単一のソリューションが得られます。

  • 一部のブラウザのエンティティデコードアルゴリズムにはバグがあるか、一部の名前付き文字参照のサポートがありません。たとえば、Internet Explorerは、改行しないスペース(&nbsp;)を正しくデコードしてレンダリングしますが、DOM要素のinnerTextプロパティを介して改行しないスペースではなく通常のスペースとして報告し、<textarea>ハックを解除します(マイナーな方法でのみです)。さらに、IE 8および9 、HTML 5に追加された新しい名前付き文字参照をサポートしていませんの作成者は、http://mathias.html5.org/tests/htmlで名前付き文字参照サポートのテストもホストしています。 /名前付き文字参照/。IE 8では、1,000を超えるエラーが報告されます。

    エンティティのデコードに関連するブラウザのバグから隔離したい場合、および/または名前付き文字参照の全範囲を処理できるようにしたい場合は、<textarea>ハックを回避できません。彼のようなライブラリが必要になります。

  • 彼はこの方法でハックが少なくなるように感じています。


4
+1 jQueryはすべてのソリューションではありません。ジョブに適したツールを使用します。
Mathias Bynens、2014年

これらは、HTMLエンティティをデコードする最良の方法です。他のすべての回答(これと同様の質問について)は、innerHTML(新しいHTML要素を作成し、HTMLコードを処理してから、その要素のinnerHTMLを取得します。非常に注意していない場合、これはXSS攻撃に対して脆弱です。詳細はこちらを参照してください)、またはUnderscore.js unescapeまたはLodash unescapeメソッドを使用することをお勧めします。どちらも不完全です(いくつかのHTMLエンティティでのみ機能します)。彼のライブラリは最も完全で安全なオプションです!
ANDS

18

エンコード:

$("<textarea/>").html('<a>').html();      // return '&lt;a&gt'

デコード:

$("<textarea/>").html('&lt;a&gt').val()   // return '<a>'

3
うまくいく答えがすでにあり、これはこれとほとんど同じです。重複する答えは必要ありません
markasoftware

4
これが正しい答えです。トムの回答はDIV要素を使用しているため、その回答はXSSに対して脆弱です。
Francisco Hodge

2
これは明確にするための最良の答えです。
Dan Randolph

4

使用する

myString = myString.replace( /\&amp;/g, '&' );

JavaScriptにはエンティティを処理するためのネイティブライブラリがないため、サーバー側で行うのが最も簡単です。また、JavaScriptを拡張するさまざまなフレームワークの検索結果の上部近くには何も見つかりませんでした。

「JavaScript HTMLエンティティ」を検索すると、その目的のためにいくつかのライブラリが見つかるかもしれませんが、それらはおそらく上記のロジックを中心に構築されます-エンティティごとにエンティティを置き換えます。


0

HTMLボタンの値として、HTMLエンティティ文字(⇓)が必要でした。ブラウザの最初からHTMLコードが適切に見えます。

<input type="button" value="Embed & Share  &dArr;" id="share_button" />

次に、文字も表示するトグルを追加しました。これは私の解決策です

$("#share_button").toggle(
    function(){
        $("#share").slideDown();
        $(this).attr("value", "Embed & Share " + $("<div>").html("&uArr;").text());
    }

これにより、ボタンに再び⇓が表示されます。これが誰かの役に立つことを願っています。


ユニコードエスケープシーケンス(つまり"Embed & Share \u21d1")を使用する方が簡単"Embed & Share ⇑"ですが、UTF-8(またはUTF-16、または⇑文字をサポートするその他のエンコーディング)でスクリプトを提供できる場合はさらに良いでしょう。DOM要素を使用してHTMLエンティティを解析し、任意のUnicode文字をJavaScript文字列にベイク処理することは、Rube Goldbergを誇りに思う賢明で創造的なアプローチですが、良い方法ではありません。Unicodeエスケープは、このユースケースを処理するための言語です。
マークアメリー2014年

0

HTMLエンティティのカスタム関数を作成する必要があります。

function htmlEntities(str) {
return String(str).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g,'&gt;').replace(/"/g, '&quot;');
}

私にはわからない、それが私を助けてくれた+1 l
Szymon Toda

一部のエンティティのみを処理するため、おそらく反対票が投じられました。
Jasen 2017年

元の質問は、エンティティをデコードする方法でした—これは、望ましいことのを行います。非常に限定された文字セットエンティティにエンコードします。反対投票のツールチップが言うように、「この回答は役に立ちません」。4年経ってもまだ正のスコアを持っていることに驚いています。
Stephen P

0

以下の文字列があるとします。

私たちのデラックスキャビンは暖かく居心地の良い&amp; 快適

var str = $("p").text(); // get the text from <p> tag
$('p').html(str).text();  // Now,decode html entities in your variable i.e 

strと代入する

鬼ごっこ。

それでおしまい。


0

ExtJSユーザーの場合、たとえば、ライブラリ関数の戻り値がinnerHTMLコンテンツである場合など、すでにエンコードされた文字列がある場合は、次のExtJS関数を検討してください。

Ext.util.Format.htmlDecode(innerHtmlContent)

これは5つのHTMLエンティティに対してのみ機能します。これは、ドキュメントソースコードで確認できます
ANDS

0

Stringクラスを拡張します。

String::decode = ->
  $('<textarea />').html(this).text()

そしてメソッドとして使用します:

"&lt;img src='myimage.jpg'&gt;".decode()

0

これを試して :

var htmlEntities = "&lt;script&gt;alert('hello');&lt;/script&gt;";
var htmlDecode =$.parseHTML(htmlEntities)[0]['wholeText'];
console.log(htmlDecode);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

parseHTMLはJqueryライブラリの関数であり、指定された文字列に関する詳細を含む配列を返します。

場合によっては文字列が大きいため、関数はコンテンツを多くのインデックスに分離します。

すべてのインデックスデータを取得するには、任意のインデックスに移動してから、「wholeText」というインデックスにアクセスする必要があります。

インデックス0を選択したのは、それがすべてのケースで機能するためです(小さいストリングまたは大きいストリング)。


このコードスニペットが解決策となる場合もありますが、説明を含めると、投稿の品質を向上させるのに役立ちます。あなたは将来の読者のための質問に答えていることを覚えておいてください、そしてそれらの人々はあなたのコード提案の理由を知らないかもしれません。
ヨハン

説明が追加されます...ありがとうございました:)
Fawaz Al Romy

-1

まだ1つの問題があります:エスケープされた文字列は、入力値に割り当てられたときに読みやすく見えません

var string = _.escape("<img src=fake onerror=alert('boo!')>");
$('input').val(string);

例:https ://jsfiddle.net/kjpdwmqa/3/


これは質問に対する答えではありません。OPはHTMLエンティティのデコード(エスケープ解除)を要求しますが、この回答escapeではUnderscore.jsのメソッドを使用しています。また、コードサンプルがOPの問題をどのように解決するかについての説明もありません。
ands

-1

または、ライブラリもあります。

ここ、https://cdnjs.com/libraries/he

npm install he                 //using node.js

<script src="js/he.js"></script>  //or from your javascript directory

使い方は次のとおりです...

//to encode text 
he.encode('© Ande & Nonso® Company LImited 2018');  

//to decode the 
he.decode('&copy; Ande &amp; Nonso&reg; Company Limited 2018');

乾杯。


簡単なコード例と、いつ、なぜ彼のライブラリを使用する必要があるかについての十分な説明とともに、完全な彼のライブラリに関する答えはすでにあります
and

-3

jQueryでHTMLエンティティをデコードするには、次の関数を使用します。

function html_entity_decode(txt){
    var randomID = Math.floor((Math.random()*100000)+1);
    $('body').append('<div id="random'+randomID+'"></div>');
    $('#random'+randomID).html(txt);
    var entity_decoded = $('#random'+randomID).html();
    $('#random'+randomID).remove();
    return entity_decoded;
}

使い方:

JavaScript:

var txtEncoded = "&aacute; &eacute; &iacute; &oacute; &uacute;";
$('#some-id').val(html_entity_decode(txtEncoded));

HTML:

<input id="some-id" type="text" />

-3

最も簡単な方法は、クラスセレクターを要素に設定し、次のコードを使用することです。

$(function(){
    $('.classSelector').each(function(a, b){
        $(b).html($(b).text());
    });
});

もう何も必要ありません!

私はこの問題を抱えていて、この明確な解決策を見つけ、それはうまく機能しました。


これはOPの質問に対する回答ではありません。OPはSTRINGのHTMLエンティティをデコードするように要求します。これはOPの問題を解決しないだけでなく、HTML要素内のエスケープされたHTMLエンティティを、実行すべきではないエンティティで置き換えます。
ANDS

-3

これは、選択したソリューションの正反対です。

var decoded = $("<div/>").text(encodedStr).html();
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.