Búsqueda de sitios web

JavaScript - ¿Cuál es la forma correcta de decodificar una cadena que tiene entidades HTML especiales?


Supongamos que recibo algo de JSON de una solicitud de servicio que se ve así:

{
    "message": "We're unable to complete your request at this time."
}

No estoy seguro de por qué ese apóstrofe está codificado así ('); todo lo que sé es que quiero decodificarlo.

Aquí tienes un enfoque usando jQuery que me vino a la cabeza:

function decodeHtml(html) {
    return $('<div>').html(html).text();
}

Eso parece (muy) chapucero, sin embargo. ¿Cuál es una mejor manera? ¿Hay una manera 'correcta'?

Respuesta #1

Esta es mi forma favorita de descifrar caracteres HTML. La ventaja de usar este código es que las etiquetas también se conservan.

function decodeHtml(html) {
    var txt = document.createElement("textarea");
    txt.innerHTML = html;
    return txt.value;
}

Ejemplo: http://jsfiddle.net/k65s3/

Entrada :

Entity:&nbsp;Bad attempt at XSS:<script>alert('new\nline?')</script><br>

Salida :

Entity: Bad attempt at XSS:<script>alert('new\nline?')</script><br>

Respuesta #2

No uses el DOM para esto si te importa la compatibilidad con los legados. Usar el DOM para decodificar entidades HTML (como se sugiere en la respuesta actualmente aceptada) conduce a diferencias en los resultados entre navegadores en navegadores no modernos.

Para una solución robusta y determinista que decodifique referencias de caracteres según el algoritmo del estándar HTML, utiliza la biblioteca he. De su README:

he (por "entidades HTML") es un codificador/decodificador robusto de entidades HTML escrito en JavaScript. Soporta todas las referencias estandarizadas de caracteres con nombre según HTML, gestiona andas ambiguas y otros casos límite igual que un navegador, cuenta con una suite de pruebas extensa y — a diferencia de muchas otras soluciones JavaScript — maneja símbolos Unicode astrales sin problemas. Hay una demostración online disponible.

Así es como lo usarías:

he.decode("We&#39;re unable to complete your request at this time.");
→ "We're unable to complete your request at this time."

Aviso legal: Soy el autor de la biblioteca.

Consulta esta respuesta de Stack Overflow para obtener más información.

Respuesta #3

Si no quieres usar html/dom, podrías usar regex. No he probado esto; pero algo parecido a:

function parseHtmlEntities(str) {
    return str.replace(/&#([0-9]{1,3});/gi, function(match, numStr) {
        var num = parseInt(numStr, 10); // read num as normal number
        return String.fromCharCode(num);
    });
}

[editar]

Nota: esto solo funcionaría para entidades HTML numéricas, y no para cosas como &oring;.

[Editar 2]

Arreglé la función (algunos errores tipográficos), prueba aquí: http://jsfiddle.net/Be2Bd/1/

Respuesta #4

Hay una función de JS para manejar entidades con estilo &#xxxx:
función en GitHub

// encode(decode) html text into html entity
var decodeHtmlEntity = function(str) {
  return str.replace(/&#(\d+);/g, function(match, dec) {
    return String.fromCharCode(dec);
  });
};

var encodeHtmlEntity = function(str) {
  var buf = [];
  for (var i=str.length-1;i>=0;i--) {
    buf.unshift(['&#', str[i].charCodeAt(), ';'].join(''));
  }
  return buf.join('');
};

var entity = '&#39640;&#32423;&#31243;&#24207;&#35774;&#35745;';
var str = '高级程序设计';

let element = document.getElementById("testFunct");
element.innerHTML = (decodeHtmlEntity(entity));

console.log(decodeHtmlEntity(entity) === str);
console.log(encodeHtmlEntity(str) === entity);
// output:
// true
// true
<div><span id="testFunct"></span></div>

Respuesta #5

jQuery codificará y decodificará por ti.

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>
<script>
$(document).ready(function() {
   $("#encoded")
  .text(htmlEncode("<img src onerror='alert(0)'>"));
   $("#decoded")
  .text(htmlDecode("&lt;img src onerror='alert(0)'&gt;"));
});
</script>

<span>htmlEncode() result:</span><br/>
<div id="encoded"></div>
<br/>
<span>htmlDecode() result:</span><br/>
<div id="decoded"></div>

Respuesta #6

_.unescape hace lo que estás buscando

https://lodash.com/docs/#unescape

Artículos relacionados