解码其中包含特殊HTML实体的字符串的正确方法是什么?

Dan*_*Tao 184 javascript jquery html-entities

假设我从服务请求中获得了一些JSON,如下所示:

{
    "message": "We're unable to complete your request at this time."
}
Run Code Online (Sandbox Code Playgroud)

我不确定为什么那个抄袭被编码为那个('); 我所知道的是我想解码它.

这是一种使用jQuery的方法,它突然出现在我脑海中:

function decodeHtml(html) {
    return $('<div>').html(html).text();
}
Run Code Online (Sandbox Code Playgroud)

但这似乎(非常)hacky.什么是更好的方式?有"正确"的方式吗?

Rob*_*b W 360

这是我最喜欢的HTML字符解码方式.使用此代码的优点是标记也被保留.

function decodeHtml(html) {
    var txt = document.createElement("textarea");
    txt.innerHTML = html;
    return txt.value;
}
Run Code Online (Sandbox Code Playgroud)

示例:http://jsfiddle.net/k65s3/

输入:

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

输出:

Entity: Bad attempt at XSS:<script>alert('new\nline?')</script><br>
Run Code Online (Sandbox Code Playgroud)

  • 哦等等,我明白了:你专门使用`textarea`以便保留标签(正如你所说),但HTML实体仍然会被解码.很聪明...... (24认同)
  • 这是可以接受的.这是解码HTML的最佳方式.没有标记被传递,与原始解决方案不同,后者解析(因此隐藏)标记. (3认同)
  • 啊,看起来基本上与我采用的方法相同,但没有 jQuery 依赖(这很好)。但它看起来不还是很老套吗?或者我应该对此感到完全满意? (2认同)

Mat*_*ens 94

不要使用DOM来执行此操作.使用DOM解码HTML实体(如当前接受的答案中所建议的)会导致跨浏览器结果的差异.

对于根据HTML标准的算法解码字符引用一个强大的和确定性的解决方案,使用的库.从其自述文件:

(对于"HTML实体")是一个用JavaScript编写的健壮的HTML实体编码器/解码器.它支持所有标准化的命名字符引用,根据HTML,处理模糊的&符号和其他边缘情况,就像浏览器一样,具有广泛的测试套件,并且 - 与许多其他JavaScript解决方案相反 - 处理星体Unicode符号就好了.提供在线演示.

这是你如何使用它:

he.decode("We&#39;re unable to complete your request at this time.");
? "We're unable to complete your request at this time."
Run Code Online (Sandbox Code Playgroud)

免责声明:我是图书馆的作者.

有关更多信息,请参阅此Stack Overflow答案.

  • 这个库压缩后有 30KB...我不想为我必须在 JS 中解决的每个小问题都获取新的库。 (11认同)
  • 我在NodeJS,所以对我来说这是唯一可用的解决方案. (8认同)
  • “导致跨浏览器结果差异的重要性”。是?在哪个浏览器中结果可能会有很大不同?你能给我确切的例子吗(这是你心目中最重要的)?我不想使用过多的第三方库,所以我想先了解一下。 (2认同)

Alx*_*ndr 30

如果你不想使用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);
    });
}
Run Code Online (Sandbox Code Playgroud)

[编辑]

注意:这只适用于数字html实体,而不适用于&oring;等.

[编辑2]

修复了函数(一些拼写错误),在这里测试:http://jsfiddle.net/Be2Bd/1/

  • 我已经评论过它们不会被解析的事实.要解析这些,您需要某种类型的哈希映射(查找).但是,如果此代码是自动生成的(例如),那么它有可能始终返回数值.我只提供了一种纯粹的js方式(没有DOM),不是说它解决了一般问题,而是更具体的问题. (4认同)
  • 那么`&amp;`和其他命名实体怎么样?这些仍未在此实现中解析. (2认同)
  • 在正则表达式匹配 `/(pattern)/gi` 中,不需要忽略大小写的 `i` 后缀,因为这只会匹配 _numbers_。随着 davewoodhall 的评论,我正在使用 `/&amp;#([0-9]{1,4});/g` (2认同)

Jas*_*ams 25

jQuery将为您编码和解码.

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

function htmlEncode(value) {
  return $('<textarea/>').text(value).html();
}
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

  • 我不同意.Textarea提供安全性,其他元素,如div,不会.如果您使用div而不是textarea,则输入中的任何非编码javascript都将在浏览器中呈现.textarea通过将输入视为文本而不是html来解决这个问题.我没有尝试过其他元素来了解它们的行为方式. (5认同)

hyp*_*ers 20

有一个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
Run Code Online (Sandbox Code Playgroud)

  • 谢谢你。这个函数在#gatsbyjs 应用程序中工作得很好,在静态 HTML 构建期间无法定义`document`。 (5认同)
  • 应该这样做! (2认同)
  • 就是这样!没有 lib 混乱,没有 DOM 操作,没有 html 注入。 (2认同)

tld*_*ldr 8

_.unescape 做你想要的

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

  • 它只是替换了一些编码字符 - 如果你有例如&nbsp; 它保持原样. (2认同)