web-dev-qa-db-ja.com

デコード(& A) JavaScriptで&に戻る

私はのような文字列があります

var str = 'One & two & three';

webサーバーによってHTMLにレンダリングされます。これらの文字列をに変換する必要があります

'One & two & three'

現在、それは私がやっていることです(jQueryの助けを借りて):

$(document.createElement('div')).html('{{ driver.person.name }}').text()

しかし、私はそれを間違ってやっているという不安な気持ちを持っています。私が試してみました

unescape("&")

しかし、それはうまくいかないようで、decodeURI/decodeURIComponentもしません。

他に、よりネイティブでエレガントな方法はありますか?

202
Art

JavaScriptからHTML(テキストなど)を解釈するためのより近代的なオプションは、DOMParser APIでのHTMLサポートです( MDNのここを参照 )。これにより、ブラウザのネイティブHTMLパーサーを使用して文字列をHTMLドキュメントに変換できます。 2014年後半以降、すべての主要ブラウザの新しいバージョンでサポートされています。

テキストの内容をデコードしたいだけであれば、それを唯一の内容として文書本体に入れ、その文書を解析してその.body.textContentを取り出すことができます。

var encodedStr = 'hello & world';

var parser = new DOMParser;
var dom = parser.parseFromString(
    '<!doctype html><body>' + encodedStr,
    'text/html');
var decodedString = dom.body.textContent;

console.log(decodedString);

DOMParserのドラフト仕様 を見るとわかるように、JavaScriptは解析済み文書に対しては有効になっていないので、セキュリティーを気にせずにこのテキスト変換を実行できます。

parseFromString(str, type)メソッドは、タイプに応じて、次の手順を実行する必要があります。

  • "text/html"

    strHTML parserで解析し、新しく作成されたDocumentを返します。

    スクリプトフラグは "無効"に設定する必要があります。

    注意

    script要素は実行不可能とマークされ、noscriptの内容はマークアップとして解析されます。

これはこの質問の範囲を超えていますが、、解析されたDOMノード自体(テキストの内容だけではなく)を取って移動する場合は注意してください。ライブドキュメントDOMに対しては、それらのスクリプティングが再度有効にされる可能性があり、セキュリティ上の懸念がある可能性があります。まだ調査していないので注意してください。

75
Jeremy

すべてのエンコードされたHTMLエンティティをデコードする必要がありますか、それとも単に&amp;自体をデコードする必要がありますか。

&amp;を処理するだけでよい場合は、これを実行できます。

var decoded = encoded.replace(/&amp;/g, '&');

すべてのHTMLエンティティをデコードする必要がある場合は、jQueryなしでそれを実行できます。

var elem = document.createElement('textarea');
elem.innerHTML = encoded;
var decoded = elem.value;

この回答の以前のバージョンのセキュリティホールを浮き彫りにしている以下のMarkのコメントに注意してください、そして潜在的なXSS脆弱性を軽減するためにtextareaよりdivを使うことを勧めます。これらの脆弱性は、jQueryを使用しているか、普通のJavaScriptを使用しているかにかかわらず存在します。

264
LukeH

Matthias Bynensにはこのためのライブラリがあります。 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"

要素のHTMLコンテンツを設定してからそのテキストコンテンツを読み返すことを含むハッキングよりも優先することをお勧めします。そのようなアプローチはうまくいく可能性がありますが、信頼できないユーザー入力で使用された場合、見かけ上危険であり、XSSの機会を提示します。

本当にライブラリにロードできない場合は、 この回答 で説明されているtextareaハックを使用して、ほぼ重複する質問をすることができます。私が知っているセキュリティホール:

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

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

しかし、セキュリティ上の問題に注意してください。これは、これと同様のアプローチに影響を及ぼします。リンクされた回答に記載されています。このアプローチはハックです、そして将来のtextarea(あるいは特定のブラウザでのバグ)の許容される内容への変更は突然XSSホールがある日にそれに依存するコードに通じるかもしれません。

38
Mark Amery
var htmlEnDeCode = (function() {
    var charToEntityRegex,
        entityToCharRegex,
        charToEntity,
        entityToChar;

    function resetCharacterEntities() {
        charToEntity = {};
        entityToChar = {};
        // add the default set
        addCharacterEntities({
            '&amp;'     :   '&',
            '&gt;'      :   '>',
            '&lt;'      :   '<',
            '&quot;'    :   '"',
            '&#39;'     :   "'"
        });
    }

    function addCharacterEntities(newEntities) {
        var charKeys = [],
            entityKeys = [],
            key, echar;
        for (key in newEntities) {
            echar = newEntities[key];
            entityToChar[key] = echar;
            charToEntity[echar] = key;
            charKeys.Push(echar);
            entityKeys.Push(key);
        }
        charToEntityRegex = new RegExp('(' + charKeys.join('|') + ')', 'g');
        entityToCharRegex = new RegExp('(' + entityKeys.join('|') + '|&#[0-9]{1,5};' + ')', 'g');
    }

    function htmlEncode(value){
        var htmlEncodeReplaceFn = function(match, capture) {
            return charToEntity[capture];
        };

        return (!value) ? value : String(value).replace(charToEntityRegex, htmlEncodeReplaceFn);
    }

    function htmlDecode(value) {
        var htmlDecodeReplaceFn = function(match, capture) {
            return (capture in entityToChar) ? entityToChar[capture] : String.fromCharCode(parseInt(capture.substr(2), 10));
        };

        return (!value) ? value : String(value).replace(entityToCharRegex, htmlDecodeReplaceFn);
    }

    resetCharacterEntities();

    return {
        htmlEncode: htmlEncode,
        htmlDecode: htmlDecode
    };
})();

これはExtJSのソースコードからのものです。

23
WaiKit Kung

element.innerTextもトリックを行います。

15
avg_joe

私のようにそれを探しているのであれば - その間、Nice and safe JQueryメソッドがあります。

https://api.jquery.com/jquery.parsehtml/

あなたはf.ex.することができますコンソールにこれを入力してください。

var x = "test &amp;";
> undefined
$.parseHTML(x)[0].textContent
> "test &"

そのため、$ .parseHTML(x)は配列を返します。テキスト内にHTMLマークアップがある場合、array.lengthは1より大きくなります。

8
cslotty

あなたはLodashのエスケープ/エスケープ機能を使用することができます https://lodash.com/docs/4.17.5#unescape

import unescape from 'lodash/unescape';

const str = unescape('fred, barney, &amp; pebbles');

strは'fred, barney, & pebbles'になります

7
I am L

jQueryはあなたのためにエンコードおよびデコードします。ただし、divではなくtextareaタグを使用する必要があります。

var str1 = 'One & two & three';
var str2 = "One &amp; two &amp; three";
  
$(document).ready(function() {
   $("#encoded").text(htmlEncode(str1)); 
   $("#decoded").text(htmlDecode(str2));
});

function htmlDecode(value) {
  return $("<textarea/>").html(value).text();
}

function htmlEncode(value) {
  return $('<textarea/>').text(value).html();
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>

<div id="encoded"></div>
<div id="decoded"></div>
6
Jason Williams

まずボディのどこかに<span id="decodeIt" style="display:none;"></span>を作成します

次に、これにinnerHTMLとしてデコードする文字列を割り当てます。

document.getElementById("decodeIt").innerHTML=stringtodecode

最後に、

stringtodecode=document.getElementById("decodeIt").innerText

これが全体のコードです:

var stringtodecode="<B>Hello</B> world<br>";
document.getElementById("decodeIt").innerHTML=stringtodecode;
stringtodecode=document.getElementById("decodeIt").innerText
4
Infoglaze.com

一行の人のために:

const htmlDecode = innerHTML => Object.assign(document.createElement('textarea'), {innerHTML}).value;

console.log(htmlDecode('Complicated - Dimitri Vegas &amp; Like Mike'));
2
Ninh Pham

一般的なものをキャッチするJavaScriptソリューション:

var map = {amp: '&', lt: '<', gt: '>', quot: '"', '#039': "'"}
str = str.replace(/&([^;]+);/g, (m, c) => map[c])

これは逆です https://stackoverflow.com/a/4835406/2738039

1
Peter Brandt

私はJSON配列から&を削除するためにあらゆることを試みました。上記の例のどれも、しかし https://stackoverflow.com/users/2030321/chris 私の問題を解決するために導いた素晴らしい解決策を与えた。

var stringtodecode="<B>Hello</B> world<br>";
document.getElementById("decodeIt").innerHTML=stringtodecode;
stringtodecode=document.getElementById("decodeIt").innerText

JSONデータを配列に引き込んでいるモーダルウィンドウに挿入する方法がわからないため、使用しませんでしたが、例に基づいて試してみましたが、うまくいきました。

var modal = document.getElementById('demodal');
$('#ampersandcontent').text(replaceAll(data[0],"&amp;", "&"));

それは単純で、うまくいくから好きです。しかし、なぜそれが広く使われていないのかわからない。簡単な解決策を見つけるためにハイ&ローを検索しました。私は構文の理解を求め続け、そしてこれを使用することに何らかのリスクがあるかどうか。まだ何も見つかっていません。

0
Digexart