Come decodificare entità HTML usando jQuery?


Risposte:


437

Nota di sicurezza: l' utilizzo di questa risposta (conservata nella sua forma originale di seguito) può introdurre una vulnerabilità XSS nella tua applicazione. Non dovresti usare questa risposta. Leggi la risposta di Lucascaro per una spiegazione delle vulnerabilità in questa risposta e usa invece l'approccio di quella risposta o la risposta di Mark Amery .

In realtà, prova

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

175
Non non farlo con un input non attendibile. Molti browser caricano immagini ed eventi correlati al fuoco anche se il nodo non è collegato al DOM. Prova a correre $("<div/>").html('<img src="http://www.google.com/images/logos/ps_logo2.png" onload=alert(1337)>'). In Firefox o Safari attiva l'avviso.
Mike Samuel,

@ Mike, quindi cosa mi consigliate invece? la tua risposta di .replace () non va bene se non sai cosa stai sostituendo ...
ekkis

7
@ekkis, devi rimuovere i tag prima di provare a decodificare le entità. str.replace(/<\/?\w(?:[^"'>]|"[^"]*"|'[^']*')*>/g, "")o qualcosa di simile.
Mike Samuel,

2
Una migliore implementazione (secondo me) che toglie la maggior parte dei tag HTML (per gentile concessione di Mike) dall'input è nella mia risposta a una domanda simile . Inoltre non ha il sovraccarico di jQuery, quindi è abbastanza adatto ad altri ambienti.
Robert K

6
@MichaelStum qui la tua modifica ha invalidato sia il commento di Mike Samuel sia la risposta più votata successiva, e lo ha fatto senza risolvere effettivamente la vulnerabilità XSS per tutte le versioni di jQuery (come spiegato nella risposta di seguito). Aggiungere un avviso di sicurezza a questa risposta sarebbe ragionevole (e lo farò); rendere le altre discussioni in questa pagina prive di senso, mentre in realtà non è possibile risolvere il problema con la sicurezza!
Mark Amery,

211

Senza jQuery:

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

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

Funziona in modo simile alla risposta accettata , ma è sicuro da usare con input dell'utente non attendibile.


Problemi di sicurezza con approcci simili

Come notato da Mike Samuel , farlo con un input dell'utente <div>invece di uno <textarea>non attendibile è una vulnerabilità XSS, anche se <div>non viene mai aggiunto al 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)">')

Tuttavia, questo attacco non è possibile contro a <textarea>perché non ci sono elementi HTML a cui è consentito il contenuto di a <textarea>. Di conseguenza, tutti i tag HTML ancora presenti nella stringa 'codificata' verranno automaticamente codificati dall'entità dal browser.

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

Avvertenza : farlo usando jQuery .html()e .val()metodi invece di usare .innerHTMLed .valueè anche insicuro * per alcune versioni di jQuery, anche quando si usa atextarea . Questo perché le versioni precedenti di jQuery valutano deliberatamente ed esplicitamente gli script contenuti nella stringa passata a .html(). Quindi codice come questo mostra un avviso 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>

* Grazie a Eru Penkman per aver colto questa vulnerabilità.


6
Potrebbe essere una buona idea distruggere l'area di testo dopo averne estratto il valore:decodedString = textArea.value; textArea.remove(); return decodedString;
Werner,

2
O solo se la versione di javascript supporta effettivamente remove ():if ('remove' in Element.prototype) textArea.remove();
Werner,

6
@Werner Non appena la funzione è terminata, non ci saranno più variabili con un riferimento in modo che venga automaticamente rimosso dal Garbage Collector .
user2428118,

Sto usando questo in combinazione con .NET dal code-behind di un clic sul pulsante, e per qualche motivo la risposta accettata ha causato un postback. Questa risposta no, quindi questa è la risposta migliore per me. Grazie!
Snailer,

@Snailer $("<div />").html(string).text() eseguirà qualsiasi javascript nella stringa fornita , che sospetto sia la causa del tuo problema. La risposta accettata dovrebbe essere aggiornata a questa.
jbowman

80

Come ha detto Mike Samuel, non usare jQuery.html (). Text () per decodificare entità html poiché non è sicuro.

Utilizza invece un renderer di modelli come Moustache.js o decodeEntities dal commento di @ VyvIT.

La libreria di cintura di utilità Underscore.js includeescape e unescapemetodi, ma non sono sicuri per l'input dell'utente:

_.escape (stringa)

_.unescape (stringa)


2
Questo in realtà merita molti più voti! Sicuramente la mia soluzione preferita. unescapeOrmai erano inclusi nei documenti, a proposito.
chitarra letale,

5
_.unescape("&#39;")risulta solo "& # 39;" invece di una virgoletta singola. C'è qualcosa che mi manca o il carattere di sottolineatura non sfugge ai codici entità HTML come mostrato su: w3schools.com/tags/ref_entities.asp
Jason Axelson

6
Il bug su github è stato chiuso come "Won't fix"; ciò significa che questa soluzione non funziona e non funzionerà.
Igor Chubin,

3
Dici che i " escapee i unescapemetodi ... di Underscore non sono sicuri per l'input dell'utente" . Cosa intendi con questo? Mi sembra assurdo, ma forse mi manca qualcosa - puoi chiarire?
Mark Amery,

2
@VyvIT Tried _.unescape("&lt;img src=fake onerror=alert('boo!')&gt;")(in Chrome / FF / IE). Ma non ha mostrato alcun avviso. L'ho provato in console e anche nel mio file JS. Stesso risultato
Vivek Athalye

28

Penso che tu stia confondendo i metodi di testo e HTML. Guarda questo esempio, se usi l'HTML interno di un elemento come testo, otterrai tag HTML decodificati (secondo pulsante). Ma se li usi come HTML, otterrai la visualizzazione in formato HTML (primo pulsante).

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

Il primo pulsante scrive: ecco un contenuto HTML .

Il secondo pulsante scrive: ecco un contenuto <B> HTML </B>.

A proposito, puoi vedere un plug-in che ho trovato nel plug-in jQuery: decodifica e codifica HTML che codifica e decodifica stringhe HTML.


26

La domanda è limitata da 'with jQuery' ma potrebbe aiutare alcuni a sapere che il codice jQuery fornito nella migliore risposta qui fa quanto segue sotto ... funziona con o senza jQuery:

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

20

È possibile utilizzare la libreria he , disponibile da https://github.com/mathiasbynens/he

Esempio:

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

Ho sfidato l'autore della biblioteca alla domanda se ci fosse qualche motivo per usare questa libreria nel codice del client a favore <textarea>dell'hack fornito in altre risposte qui e altrove. Ha fornito alcune possibili giustificazioni:

  • Se si utilizza il server node.js sul lato, l'utilizzo di una libreria per la codifica / decodifica HTML offre un'unica soluzione che funziona sia sul lato client che sul lato server.

  • Alcuni algoritmi di decodifica delle entità del browser presentano bug o mancano il supporto per alcuni riferimenti ai caratteri con nome . Ad esempio, Internet Explorer decodificherà e renderizzerà &nbsp;correttamente gli spazi non interrompibili ( ) ma li riporterà come spazi ordinari anziché non interrompibili tramite la innerTextproprietà di un elemento DOM , interrompendo l' <textarea>hack (anche se solo in modo minore). Inoltre, IE 8 e 9 semplicemente non supportano nessuno dei nuovi riferimenti ai caratteri nominativi aggiunti in HTML 5. L'autore di lui ospita anche un test di supporto dei riferimenti ai caratteri denominati su http://mathias.html5.org/tests/html / nominati-caratteri-riferimenti / . In IE 8, riporta oltre mille errori.

    Se vuoi essere isolato dai bug del browser relativi alla decodifica delle entità e / o essere in grado di gestire l'intera gamma di riferimenti ai personaggi con nome, non puoi cavartela con l' <textarea>hacking; avrai bisogno di una biblioteca come lui .

  • Dannatamente ha la sensazione che fare le cose in questo modo sia meno confuso.


4
+1 jQuery non è la soluzione a tutto. Usa lo strumento giusto per il lavoro.
Mathias Bynens,

Questo è il modo migliore per decodificare entità HTML. Tutte le altre risposte (su questa e altre domande simili) usano innerHTML (crea un nuovo elemento HTML, elabora codice HTML e quindi ottiene innerHTML di quell'elemento, questo può essere vulnerabile agli attacchi XSS se non stai MOLTO attento, vedi di più ), oppure loro suggerire di utilizzare Underscore.js unescape metodi o Lodash unescape che sono entrambi incompleti (funziona solo per poche entità HTML). La libreria è l'opzione più completa e sicura!
ANDS

18

codificare:

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

decodificare:

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

3
c'è già una risposta che funziona ed è quasi identica a questa. Non abbiamo bisogno di risposte duplicate
markasoftware,

4
Questa è la risposta valida La risposta di Tom utilizza un elemento DIV, che rende tale risposta vulnerabile a XSS.
Francisco Hodge,

2
Questa è la migliore risposta per chiarezza.
Dan Randolph,

4

Uso

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

È più semplice farlo sul lato server perché apparentemente JavaScript non ha una libreria nativa per la gestione delle entità, né ho trovato alcun risultato nella parte superiore dei risultati di ricerca per i vari framework che estendono JavaScript.

Cerca "Entità HTML JavaScript" e potresti trovare alcune librerie solo per quello scopo, ma probabilmente saranno tutte costruite attorno alla logica sopra - sostituire, entità per entità.


0

Dovevo solo avere un charater di entità HTML (⇓) come valore per un pulsante HTML. Il codice HTML sembra buono fin dall'inizio nel browser:

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

Ora stavo aggiungendo un interruttore che dovrebbe anche visualizzare il carattere. Questa è la mia soluzione

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

Questo visualizza di nuovo ⇓ nel pulsante. Spero che questo possa aiutare qualcuno.


Più semplice sarebbe usare una sequenza di escape unicode (cioè "Embed & Share \u21d1"), o meglio ancora solo "Embed & Share ⇑"se sei in grado di servire il tuo script in UTF-8 (o UTF-16, o qualsiasi altra codifica che supporti il ​​carattere ⇑). Usare un elemento DOM per analizzare un'entità HTML solo per creare un carattere unicode arbitrario in una stringa JavaScript è un approccio astuto e creativo che renderebbe orgoglioso Rube Goldberg, ma non è una buona pratica; gli escape unicode sono nella lingua specifica per gestire questo caso d'uso.
Mark Amery,

0

Devi rendere la funzione personalizzata per le entità html:

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

Non ne ho idea, mi ha aiutato così +1 l-)
Szymon Toda,

forse è stato votato verso il basso perché gestisce solo alcune entità.
Jasen,

La domanda originale era come decodificare le entità - questo fa l' opposto di ciò che si desidera; si codifica un insieme estremamente limitato di caratteri in entità. Come dice la descrizione del voto negativo, "Questa risposta non è utile". Sono sorpreso che dopo 4 anni abbia ancora un punteggio netto positivo.
Stephen P,

0

Supponiamo di avere sotto String.

Le nostre cabine Deluxe sono calde, accoglienti e amp; confortevole

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

str e assegnare di nuovo a

etichetta.

questo è tutto.


0

Per gli utenti ExtJS, se si dispone già della stringa codificata, ad esempio quando il valore restituito di una funzione di libreria è il contenuto innerHTML, considerare questa funzione ExtJS:

Ext.util.Format.htmlDecode(innerHtmlContent)

Funzionerà solo per 5 entità HTML. Puoi vederlo nella documentazione e nel codice sorgente .
ANDS

0

Estendi una classe String:

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

e utilizzare come metodo:

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

0

Prova questo :

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 è una funzione nella libreria Jquery e restituirà un array che include alcuni dettagli sulla stringa specificata.

in alcuni casi la stringa è grande, quindi la funzione separerà il contenuto da molti indici.

e per ottenere tutti i dati degli indici dovresti andare su qualsiasi indice, quindi accedere all'indice chiamato "wholeText".

Ho scelto l'indice 0 perché funzionerà in tutti i casi (stringa piccola o stringa grande).


Mentre questo frammento di codice può essere la soluzione, inclusa una spiegazione aiuta davvero a migliorare la qualità del tuo post. Ricorda che stai rispondendo alla domanda per i lettori in futuro e quelle persone potrebbero non conoscere i motivi del tuo suggerimento sul codice.
Johan

La spiegazione è stata aggiunta ... Grazie :)
Fawaz Al Romy,

-1

Qui c'è ancora un problema: la stringa con escape non sembra leggibile quando assegnata al valore di input

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

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


Questa non è una risposta alla domanda. OP chiede di decodificare (unescape) l'entità HTML, ma in questa risposta stai usando il escapemetodo di Underscore.js. Inoltre non ci sono spiegazioni su come l'esempio di codice dovrebbe risolvere il problema di OP.
ANDS

-1

In alternativa, c'è anche una libreria per questo ...

qui, https://cdnjs.com/libraries/he

npm install he                 //using node.js

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

L'utilizzo è il seguente ...

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

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

Saluti.


C'è già una risposta sulla libreria che è completa, con un semplice esempio di codice e una buona spiegazione del perché e quando usare la libreria .
ANDS

-3

Per decodificare le entità HTML con jQuery, basta usare questa funzione:

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

Come usare:

Javascript:

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

HTML:

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

-3

Il modo più semplice è impostare un selettore di classe sui tuoi elementi e quindi utilizzare il seguente codice:

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

Non serve più nulla!

Ho avuto questo problema e ho trovato questa soluzione chiara e funziona benissimo.


Questa non è una risposta alla domanda di OP. OP chiede di decodificare le entità HTML in STRING, NON solo questo non risolve il problema del PO ma sostituisce anche le entità HTML sfuggite nell'elemento HTML con quelle non osservate che non dovrebbero essere fatte.
ANDS

-3

Penso che sia esattamente l'opposto della soluzione scelta.

var decoded = $("<div/>").text(encodedStr).html();
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.