Как правильно декодировать строку, содержащую специальные HTML-объекты?

Скажем, я получил немного JSON из запроса на обслуживание, который выглядит следующим образом:

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

Я не уверен, почему этот апостраф так закодирован ('); все, что я знаю, это то, что я хочу расшифровать его.

Вот один из подходов, использующий jQuery, который появился у меня в голове:

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

Хотя это кажется (очень) хакерским. Какой способ лучше? Есть ли "правильный" путь?

7 ответов

Решение

Это мой любимый способ декодирования символов HTML. Преимущество использования этого кода в том, что теги также сохраняются.

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

Пример: http://jsfiddle.net/k65s3/

Входные данные:

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

Выход:

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

Не используйте DOM для этого. Использование DOM для декодирования сущностей HTML (как предлагается в принятом в настоящее время ответе) приводит к различиям в результатах в разных браузерах.

Для надежного и детерминированного решения, которое декодирует ссылки на символы в соответствии с алгоритмом в стандарте HTML, используйте библиотеку he. Из его README:

он (для "сущностей HTML") - надежный кодер / декодер сущностей HTML, написанный на JavaScript. Он поддерживает все стандартизированные именованные ссылки на символы в соответствии с HTML, обрабатывает неоднозначные амперсанды и другие крайние случаи так же, как это делает браузер, имеет обширный набор тестов и - в отличие от многих других решений JavaScript - он отлично обрабатывает астральные символы Юникода. Доступна онлайн-демонстрация.

Вот как бы вы использовали это:

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

Отказ от ответственности: я автор библиотеки.

Смотрите этот ответ переполнения стека для получения дополнительной информации.

Если вы не хотите использовать html/dom, вы можете использовать регулярные выражения. Я не проверял это; но что-то вроде:

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

[Редактировать]

Примечание: это будет работать только для числовых html-сущностей, а не для таких вещей, как & oring;.

[Редактировать 2]

Исправлена ​​функция (некоторые опечатки), протестируйте здесь: http://jsfiddle.net/Be2Bd/1/

Есть функция JS для работы с объектами в стиле & # xxxx:
функция на 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 = '高级程序设计';
console.log(decodeHtmlEntity(entity) === str);
console.log(encodeHtmlEntity(str) === entity);
// output:
// true
// true

JQuery будет кодировать и декодировать для вас.

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>

_.unescape делает то, что вы ищете

http://underscorejs.org/

Это так хороший ответ. Вы можете использовать это с угловой, как это:

 moduleDefinitions.filter('sanitize', ['$sce', function($sce) {
    return function(htmlCode) {
        var txt = document.createElement("textarea");
        txt.innerHTML = htmlCode;
        return $sce.trustAsHtml(txt.value);
    }
}]);
Другие вопросы по тегам