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

IT技术 javascript jquery html-entities
2021-02-05 18:15:00

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

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

我不知道为什么那个撇号是这样编码的(');我只知道我想解码它。

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

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

不过,这似乎(非常)hacky。什么是更好的方法?有“正确”的方法吗?

6个回答

这是我最喜欢的解码 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>
这是可以接受的。这是解码 HTML 的最佳方式。不传递任何标签,这与您的原始解决方案不同,后者解析(从而隐藏)标签。
2021-03-19 18:15:00
不错的把戏!我已经使用了一段时间的非textarea版本,这要好得多。
2021-03-19 18:15:00
哦,等等,我明白了:您textarea专门使用以便保留标签(如您所说),但 HTML 实体仍会被解码。好聪明...
2021-03-23 18:15:00
啊,似乎与我采用的方法基本相同,但没有 jQuery 依赖(这很好)。不过,它看起来是不是仍然很笨拙?或者我应该完全适应它?
2021-03-29 18:15:00
@Leonardo 它从未附加到文档中。
2021-04-02 18:15:00

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

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

he(代表“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."

免责声明:我是he的作者

有关更多信息,请参阅此堆栈溢出答案

这个应该是正确答案。比 lodash 和下划线效果更好。
2021-03-13 18:15:00
@TaufikNurRahmanda 它指向回答该问题的链接。
2021-03-18 18:15:00
“导致跨浏览器结果差异的重要性”。是?在哪个浏览器中结果可能会有很大不同?你能给我确切的例子吗(这是你心目中最重要的)?不想使用过多的第三方库,想先了解一下。
2021-03-19 18:15:00
我在 NodeJS 中,所以对我来说这是唯一可用的解决方案。
2021-03-20 18:15:00
我正在编写一个浏览器插件来抓取页面的内容,所以基于 dom 的解决方案不是问题。这取决于上下文。
2021-03-22 18:15:00

如果你不想使用 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/

怎么样&amp;和其他命名实体?这些在这个实现中仍然没有被解析。
2021-03-11 18:15:00
不使用 > <
2021-03-14 18:15:00
我只是用这个的jsfiddle一个细微的变化,{1,3}{1,4}这也让更多的字符(如短划线&#8211;)。为了将来参考,其他任何人都将其用于其他标签,例如&gt;?
2021-03-19 18:15:00
在正则表达式匹配中/(pattern)/gii不需要忽略大小写后缀,因为这只会匹配numbers随着 davewoodhall 的评论,我正在使用/&#([0-9]{1,4});/g
2021-03-20 18:15:00
我已经评论过它们不会被解析的事实。要解析这些,您需要某种类型的哈希图(查找)。但是,如果此代码是自动生成的(据说),则它有可能始终返回数值。我只提供了一种纯 js 的方式来做到这一点(在没有 DOM 的情况下工作),并不是说它解决了一般问题,而是更具体的问题。
2021-04-07 18:15:00

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>

并进一步澄清:如果您确实希望 html 在转换后在浏览器中呈现,请将其包装在一个不是文本输入的元素中。
2021-03-23 18:15:00
我不同意。Textarea 提供了其他元素(如 div)不会提供的安全性。如果您使用 div 而不是 textarea,则输入中的任何未编码的 javascript 都将在浏览器中呈现。textarea 通过将输入视为文本...而不是 html 来解决此问题。我还没有尝试过其他元素来了解它们的行为。
2021-04-01 18:15:00
作为参考,任何“元素”都可以在这里工作。在这里完成工作的 textarea 没有什么神奇之处。但这就是说,如果您已经在使用 jQuery,我总是使用这种方法来获得出色的结果。
2021-04-05 18:15:00

有处理&#xxxx样式实体的 JS 函数
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
谢谢你。此函数在 #gatsbyjs 应用程序中运行良好,document在静态 HTML 构建期间无法定义该应用程序
2021-03-17 18:15:00
这就是方法!没有 lib 混乱,没有 DOM 操作,没有 html 注入。
2021-03-26 18:15:00
这是应该如何做的!
2021-04-09 18:15:00