Wie dekodiere ich HTML-Entitäten mit jQuery?

334

Wie verwende ich jQuery, um HTML-Entitäten in einer Zeichenfolge zu dekodieren?

EddyR
quelle
Die vorzeitige Wahl der Technologie (jQuery) lädt zu Antworten mit Sicherheitsproblemen ein. Dies ist möglicherweise besser als ein Duplikat von stackoverflow.com/questions/1912501/… geschlossen .
Wladimir Palant

Antworten:

437

Sicherheitshinweis: Die Verwendung dieser Antwort (in der unten angegebenen Originalform erhalten) kann zu einer XSS-Sicherheitsanfälligkeit in Ihrer Anwendung führen. Sie sollten diese Antwort nicht verwenden. Lesen Sie die Antwort von Lucascaro, um eine Erklärung der Schwachstellen in dieser Antwort zu erhalten, und verwenden Sie stattdessen entweder den Ansatz dieser Antwort oder die Antwort von Mark Amery .

Versuchen Sie es tatsächlich

var decoded = $("<div/>").html(encodedStr).text();
Tom
quelle
175
Sie nicht tun dies mit nicht vertrauenswürdigen Eingaben. Viele Browser laden Bilder und feuerbezogene Ereignisse, auch wenn der Knoten nicht mit dem DOM verbunden ist. Versuche zu rennen $("<div/>").html('<img src="http://www.google.com/images/logos/ps_logo2.png" onload=alert(1337)>'). In Firefox oder Safari wird die Warnung ausgelöst.
Mike Samuel
@ Mike, was empfehlen Sie stattdessen? Ihre Antwort von .replace () ist nicht gut, wenn Sie nicht wissen, was Sie ersetzen ...
ekkis
7
@ekkis, Sie müssen Tags entfernen, bevor Sie versuchen, Entitäten zu dekodieren. str.replace(/<\/?\w(?:[^"'>]|"[^"]*"|'[^']*')*>/g, "")oder etwas ähnliches.
Mike Samuel
2
Eine bessere Implementierung (meiner Meinung nach), bei der die meisten HTML-Tags (mit freundlicher Genehmigung von Mike) aus der Eingabe entfernt werden, ist meine Antwort auf eine ähnliche Frage . Es hat auch nicht den Overhead von jQuery, so dass es für andere Umgebungen gut geeignet ist.
Robert K
6
@MichaelStum Ihre Bearbeitung hier hat sowohl den Kommentar von Mike Samuel als auch die Antwort mit der nächsthöheren Stimme ungültig gemacht, ohne die XSS-Sicherheitsanfälligkeit für alle jQuery-Versionen zu beheben (wie in der Antwort unten erläutert). Das Hinzufügen einer Sicherheitswarnung zu dieser Antwort wäre sinnvoll (und ich werde dies tun). Andere Diskussionen auf dieser Seite unsinnig zu machen, ohne die Sicherheitslücke tatsächlich zu schließen, ist definitiv nicht!
Mark Amery
211

Ohne jQuery:

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

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

Dies funktioniert ähnlich wie die akzeptierte Antwort , kann jedoch sicher mit nicht vertrauenswürdigen Benutzereingaben verwendet werden.


Sicherheitsprobleme bei ähnlichen Ansätzen

Wie von Mike Samuel bemerkt , ist dies eine XSS-Sicherheitsanfälligkeit, wenn dies nicht mit einer nicht vertrauenswürdigen Benutzereingabe, <div>sondern mit einer <textarea>nicht vertrauenswürdigen Benutzereingabe erfolgt, selbst wenn die <div>niemals zum DOM hinzugefügt wird:

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)">')

Dieser Angriff ist jedoch gegen a nicht möglich, <textarea>da keine HTML-Elemente vorhanden sind, deren Inhalt zulässig ist <textarea>. Folglich werden alle HTML-Tags, die noch in der 'codierten' Zeichenfolge vorhanden sind, vom Browser automatisch entitätscodiert.

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)">'))

Achtung : Dadurch jQuery verwenden .html()und .val()anstelle der Verwendung von Methoden .innerHTMLund .valueist auch unsicher * für einige Versionen von jQuery, selbst wenn eine Verwendungtextarea . Dies liegt daran, dass ältere Versionen von jQuery Skripte, die in der übergebenen Zeichenfolge enthalten sind, absichtlich und explizit auswerten.html() . Daher zeigt Code wie dieser eine Warnung in 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>

* Vielen Dank an Eru Penkman , der diese Sicherheitsanfälligkeit entdeckt hat.

lucascaro
quelle
6
Es könnte eine gute Idee sein, den Textbereich nach dem Extrahieren seines Wertes zu zerstören:decodedString = textArea.value; textArea.remove(); return decodedString;
Werner
2
Oder nur, wenn die Version von Javascript remove () tatsächlich unterstützt:if ('remove' in Element.prototype) textArea.remove();
Werner
6
@Werner Sobald die Funktion beendet wurde, gibt es keine Variablen mehr, die einen Verweis darauf enthalten, sodass sie vom Garbage Collector automatisch entfernt werden .
user2428118
Ich verwende dies in Kombination mit .NET aus dem Code-Behind eines Button-Klicks, und aus irgendeinem Grund verursachte die akzeptierte Antwort ein Postback. Diese Antwort hat nicht geklappt, daher ist dies die beste Antwort für mich. Vielen Dank!
Snailer
@Snailer $("<div />").html(string).text() führt jedes Javascript in der angegebenen Zeichenfolge aus , was vermutlich Ihr Problem verursacht hat. Die akzeptierte Antwort sollte auf diese aktualisiert werden.
Jbowman
80

Wie Mike Samuel sagte, verwenden Sie jQuery.html (). Text () nicht, um HTML-Entitäten zu dekodieren, da dies unsicher ist.

Verwenden Sie stattdessen einen Vorlagenrenderer wie Moustache.js oder decodeEntities aus dem Kommentar von @ VyvIT.

Die Underscore.js Utility-Belt-Bibliothek enthält escapeund unescapeMethoden, die jedoch für Benutzereingaben nicht sicher sind:

_.escape (Zeichenfolge)

_.unescape (Zeichenfolge)

Alan Hamlett
quelle
2
Dies verdient tatsächlich viel mehr Stimmen! Auf jeden Fall meine bevorzugte Lösung. Sie unescapesind übrigens inzwischen in den Dokumenten enthalten.
tödliche Gitarre
5
_.unescape("&#39;")ergibt nur "& # 39;" anstelle eines einfachen Anführungszeichens. Fehlt
Jason Axelson
6
Der Fehler auf Github wurde als "Wird nicht behoben" geschlossen. Das bedeutet, dass diese Lösung nicht funktioniert und nicht funktioniert.
Igor Chubin
3
Sie sagen, dass Underscore " escapeund unescapeMethoden ... für Benutzereingaben nicht sicher sind" . Was meinst du damit? Es klingt für mich nach Unsinn, aber vielleicht fehlt mir etwas - können Sie das klarstellen?
Mark Amery
2
@VyvIT Versucht _.unescape("&lt;img src=fake onerror=alert('boo!')&gt;")(in Chrome / FF / IE). Aber es zeigte sich keine Warnung. Versuchte es in der Konsole und legte es auch in meine JS-Datei. Gleiches Ergebnis.
Vivek Athalye
28

Ich denke, Sie verwechseln die Text- und HTML-Methoden. In diesem Beispiel erhalten Sie dekodierte HTML-Tags (zweite Schaltfläche), wenn Sie den inneren HTML-Code eines Elements als Text verwenden. Wenn Sie sie jedoch als HTML verwenden, erhalten Sie die HTML-formatierte Ansicht (erste Schaltfläche).

<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>

Erste Schaltfläche schreibt: Hier ist ein HTML- Inhalt.

Zweite Schaltfläche schreibt: Hier ist ein <B> HTML </ B> -Inhalt.

Übrigens können Sie ein Plug-In sehen, das ich im jQuery-Plugin gefunden habe - HTML-Dekodierung und -Codierung , die HTML-Zeichenfolgen codiert und decodiert.

Canavar
quelle
26

Die Frage ist durch 'mit jQuery' begrenzt, aber es kann einigen helfen zu wissen, dass der in der besten Antwort hier angegebene jQuery-Code Folgendes bewirkt ... dies funktioniert mit oder ohne jQuery:

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

Sie können die Verwendung er Bibliothek von https://github.com/mathiasbynens/he

Beispiel:

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

Ich habe den Autor der Bibliothek in der Frage herausgefordert, ob es einen Grund gibt, diese Bibliothek im clientseitigen Code zu verwenden, und zwar zugunsten des <textarea>Hacks, der in anderen Antworten hier und anderswo angegeben ist. Er lieferte einige mögliche Begründungen:

  • Wenn Sie die serverseitige Datei node.js verwenden, erhalten Sie durch die Verwendung einer Bibliothek für die HTML-Codierung / -Decodierung eine einzige Lösung, die sowohl clientseitig als auch serverseitig funktioniert.

  • Die Entitätsdecodierungsalgorithmen einiger Browser weisen Fehler auf oder es fehlt die Unterstützung für einige benannte Zeichenreferenzen . Beispielsweise dekodiert und rendert Internet Explorer nicht unterbrechende Leerzeichen ( &nbsp;) korrekt, meldet sie jedoch als normale Leerzeichen anstelle von nicht unterbrechenden Leerzeichen über die innerTextEigenschaft eines DOM-Elements und unterbricht den <textarea>Hack (wenn auch nur in geringem Umfang). Zusätzlich IE 8 und 9 einfach nicht unterstützen , eine der neuen benannten Zeichenreferenzen hinzugefügt in HTML 5. Der Autor er auch einen Test der benannten Zeichenreferenz Unterstützung findet bei http://mathias.html5.org/tests/html / Named-Character-Referenzen / . In IE 8 werden über tausend Fehler gemeldet.

    Wenn Sie vor Browserfehlern im Zusammenhang mit der Entschlüsselung von Entitäten isoliert werden möchten und / oder in der Lage sein möchten, die gesamte Bandbreite der benannten Zeichenreferenzen zu verarbeiten, können Sie mit dem <textarea>Hack nicht durchkommen . Du brauchst eine Bibliothek wie er .

  • Er hat einfach das verdammte Gefühl, dass es weniger hackig ist, Dinge auf diese Weise zu tun.

Mark Amery
quelle
4
+1 jQuery ist nicht die Lösung für alles. Verwenden Sie das richtige Werkzeug für den Job.
Mathias Bynens
Dies ist der beste Weg, um HTML-Entitäten zu dekodieren. Alle anderen Antworten (auf diese und ähnliche Fragen) verwenden entweder innerHTML (neues HTML-Element erstellen, HTML-Code verarbeiten und dann innerHTML dieses Elements abrufen. Dies kann für XSS-Angriffe anfällig sein, wenn Sie nicht SEHR vorsichtig sind, siehe mehr ) oder sie Schlagen Sie die Verwendung von Underscore.js unescape- oder Lodash unescape- Methoden vor, die beide unvollständig sind (funktioniert nur für wenige HTML-Entitäten). Die Bibliothek ist die vollständigste und sicherste Option!
ands
18

kodieren:

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

dekodieren:

$("<textarea/>").html('&lt;a&gt').val()   // return '<a>'
user4064396
quelle
3
Es gibt bereits eine Antwort, die funktioniert, und sie ist fast identisch mit dieser. Wir brauchen keine doppelten Antworten
markasoftware
4
Dies ist die gültige Antwort. Toms Antwort verwendet ein DIV-Element, wodurch diese Antwort für XSS anfällig wird.
Francisco Hodge
2
Dies ist die beste Antwort für Klarheit.
Dan Randolph
4

Verwenden

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

Es ist am einfachsten, dies auf der Serverseite zu tun, da JavaScript anscheinend keine native Bibliothek für die Verarbeitung von Entitäten hat und ich auch keine in den Suchergebnissen für die verschiedenen Frameworks gefunden habe, die JavaScript erweitern.

Suchen Sie nach "JavaScript-HTML-Entitäten", und Sie finden möglicherweise einige Bibliotheken für diesen Zweck, aber sie werden wahrscheinlich alle auf der obigen Logik basieren - ersetzen Sie Entität durch Entität.

Peter Mortensen
quelle
0

Ich musste nur einen HTML-Entity-Charater (⇓) als Wert für eine HTML-Schaltfläche haben. Der HTML-Code sieht im Browser von Anfang an gut aus:

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

Jetzt habe ich einen Schalter hinzugefügt, der auch den Charakter anzeigen soll. Das ist meine Lösung

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

Dies zeigt ⇓ erneut in der Schaltfläche an. Ich hoffe das könnte jemandem helfen.

philipp
quelle
Einfacher wäre es, eine Unicode-Escape-Sequenz (dh "Embed & Share \u21d1") zu verwenden, oder noch besser, "Embed & Share ⇑"wenn Sie Ihr Skript in UTF-8 (oder UTF-16 oder einer anderen Codierung, die das Zeichen ⇑ unterstützt) bereitstellen können. Die Verwendung eines DOM-Elements zum Parsen einer HTML-Entität, nur um ein beliebiges Unicode-Zeichen in eine JavaScript-Zeichenfolge zu backen, ist ein gerissener und kreativer Ansatz, der Rube Goldberg stolz machen würde, aber keine gute Praxis ist. Unicode-Escapezeichen sind in der Sprache speziell für diesen Anwendungsfall.
Mark Amery
0

Sie müssen benutzerdefinierte Funktionen für HTML-Entitäten erstellen:

function htmlEntities(str) {
return String(str).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g,'&gt;').replace(/"/g, '&quot;');
}
Ali
quelle
Ich habe keine Ahnung, es hat mir so geholfen +1 l-)
Szymon Toda
Möglicherweise wurde es abgelehnt, weil es nur einige Entitäten behandelt.
Jasen
Die ursprüngliche Frage war, wie Entitäten zu dekodieren sind - dies macht das Gegenteil von dem, was gewünscht wird; Es codiert eine äußerst begrenzte Anzahl von Zeichen in Entitäten. Wie der Tooltip zur Abstimmung lautet: "Diese Antwort ist nicht nützlich". Ich bin überrascht, dass es nach 4 Jahren immer noch einen positiven Nettowert hat.
Stephen P
0

Angenommen, Sie haben unten String.

Unsere Deluxe-Kabinen sind warm, gemütlich & amp; komfortabel

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

str und zurück zuweisen

Etikett.

das ist es.

Anirudh Sood
quelle
0

Wenn Sie für ExtJS-Benutzer bereits über die codierte Zeichenfolge verfügen, z. B. wenn der zurückgegebene Wert einer Bibliotheksfunktion der innerHTML-Inhalt ist, sollten Sie diese ExtJS-Funktion berücksichtigen:

Ext.util.Format.htmlDecode(innerHtmlContent)
Ilan
quelle
Dies funktioniert nur für 5 HTML-Entitäten. Sie können dies in der Dokumentation und im Quellcode sehen .
ands
0

Erweitern Sie eine String-Klasse:

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

und als Methode verwenden:

"&lt;img src='myimage.jpg'&gt;".decode()
Sergio Belevskij
quelle
0

Versuche dies :

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 ist eine Funktion in der Jquery-Bibliothek und gibt ein Array zurück, das einige Details zum angegebenen String enthält.

In einigen Fällen ist der String groß, sodass die Funktion den Inhalt in viele Indizes aufteilt.

und um alle Indexdaten zu erhalten, sollten Sie zu einem beliebigen Index gehen und dann auf den Index mit dem Namen "WholeText" zugreifen.

Ich habe Index 0 gewählt, weil er in allen Fällen funktioniert (kleiner oder großer String).

Fawaz Al Romy
quelle
Während dieses Code-Snippet die Lösung sein kann, hilft das Hinzufügen einer Erklärung wirklich, die Qualität Ihres Beitrags zu verbessern. Denken Sie daran, dass Sie die Frage für Leser in Zukunft beantworten und diese Personen möglicherweise die Gründe für Ihren Codevorschlag nicht kennen.
Johan
Die Erklärung wurde hinzugefügt ... Danke :)
Fawaz Al Romy
-1

Hier ist noch ein Problem: Escaped String sieht nicht lesbar aus, wenn es dem Eingabewert zugewiesen wird

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

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

Lauris Kuznecovs
quelle
Dies ist keine Antwort auf die Frage. OP fordert Sie auf, eine HTML-Entität zu dekodieren (zu entschlüsseln). In dieser Antwort verwenden Sie jedoch die escapeMethode Underscore.js. Es gibt auch keine Erklärung, wie Ihr Codebeispiel das Problem von OP lösen sollte.
ands
-1

Alternativ gibt es auch eine Bibliothek dafür ..

hier https://cdnjs.com/libraries/he

npm install he                 //using node.js

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

Die Verwendung ist wie folgt ...

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

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

Prost.

Ande Caleb
quelle
Es gibt bereits eine vollständige Antwort auf die Bibliothek mit einem einfachen Codebeispiel und einer guten Erklärung, warum und wann Sie die Bibliothek verwenden sollten .
ands
-3

Verwenden Sie zum Dekodieren von HTML-Entitäten mit jQuery einfach die folgende Funktion:

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;
}

Wie benutzt man:

Javascript:

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

HTML:

<input id="some-id" type="text" />
Fred
quelle
-3

Am einfachsten ist es, eine Klassenauswahl für Ihre Elemente festzulegen und dann den folgenden Code zu verwenden:

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

Nichts mehr nötig!

Ich hatte dieses Problem und fand diese klare Lösung und es funktioniert gut.

Hamidreza
quelle
Dies ist keine Antwort auf die Frage von OP. OP fordert Sie auf, HTML-Entitäten in STRING zu dekodieren. Dies löst nicht nur nicht das Problem des OP, sondern ersetzt auch maskierte HTML-Entitäten im HTML-Element durch nicht gekoppelte, was nicht getan werden sollte.
Ands
-3

Ich denke, das ist das genaue Gegenteil der gewählten Lösung.

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