我有一些与XML-RPC后端通信的JavaScript代码。 XML-RPC返回如下形式的字符串:

<img src='myimage.jpg'>

然而,当我使用JavaScript将字符串插入到HTML中时,它们会逐字呈现。我看到的不是图像,而是字符串:

<img src='myimage.jpg'>

我猜想HTML是通过XML-RPC通道转义的。

如何在JavaScript中解除字符串转义?我尝试了这个页面上的技巧,但没有成功:http://paulschreiber.com/blog/2008/09/20/javascript-how-to-unescape-html-entities/

诊断这个问题的其他方法是什么?


当前回答

Matthias Bynens有一个这样的库:https://github.com/mathiasbynens/he

例子:

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

我建议使用它,而不是设置元素的HTML内容,然后读取它的文本内容。这种方法是可行的,但如果用于不可信的用户输入,则具有欺骗性的危险,并提供XSS机会。

如果你真的不能忍受在库中加载,你可以使用这个回答中描述的textarea黑客来回答一个几乎重复的问题,这与各种类似的方法不同,没有我所知道的安全漏洞:

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

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

但是请注意安全问题,影响类似的方法,我在链接的答案中列出!这种方法是一种hack,将来对文本区域允许内容的更改(或特定浏览器中的错误)可能会导致依赖它的代码有一天突然出现XSS漏洞。

其他回答

闭包可以避免创建不必要的对象。

const decodingHandler = (() => {
  const element = document.createElement('div');
  return text => {
    element.innerHTML = text;
    return element.textContent;
  };
})();

一种更简洁的方式

const decodingHandler = (() => {
  const element = document.createElement('div');
  return text => ((element.innerHTML = text), element.textContent);
})();

这里给出的大多数答案都有一个巨大的缺点:如果您试图转换的字符串不受信任,那么您将以跨站点脚本(XSS)漏洞告终。对于已接受答案中的函数,考虑如下:

htmlDecode("<img src='dummy' onerror='alert(/xss/)'>");

这里的字符串包含一个未转义的HTML标记,因此htmlDecode函数将实际运行字符串中指定的JavaScript代码,而不是解码任何内容。

这可以通过使用所有现代浏览器都支持的DOMParser来避免:

html解码(输入)功能 瓦尔多克=新住户。parseFromString(输入,“短信/ html”); 归来医生。documentElement textContent; 的 控制台.log(htmlDecode(“< img src=‘myimage.jpg’>’) <img src='myimage.jpg'> ' 控制台(htmlDecode(“<img src=‘dummy’on误差=‘alert(/xss/)'>) - "

该函数保证不会运行任何JavaScript代码作为副作用。任何HTML标记将被忽略,只返回文本内容。

兼容性说明:使用DOMParser解析HTML至少需要Chrome 30、Firefox 12、Opera 17、Internet Explorer 10、Safari 7.1或Microsoft Edge。因此,所有没有支持的浏览器都已经超过了它们的EOL,截至2017年,唯一能在野外看到的是旧的Internet Explorer和Safari版本(通常这些版本仍然不够多)。

元素。innerText也可以做到这一点。

其他答案都有问题。

document.createElement('div')方法(包括使用jQuery的方法)执行传递给它的任何javascript(一个安全问题),DOMParser.parseFromString()方法修饰空白。这是一个纯javascript解决方案,没有任何问题:

function htmlDecode(html) {
    var textarea = document.createElement("textarea");
    html= html.replace(/\r/g, String.fromCharCode(0xe000)); // Replace "\r" with reserved unicode character.
    textarea.innerHTML = html;
    var result = textarea.value;
    return result.replace(new RegExp(String.fromCharCode(0xe000), 'g'), '\r');
}

TextArea是专门用来避免执行js代码。它通过了这些:

htmlDecode('&lt;&amp;&nbsp;&gt;'); // returns "<& >" with non-breaking space.
htmlDecode('  '); // returns "  "
htmlDecode('<img src="dummy" onerror="alert(\'xss\')">'); // Does not execute alert()
htmlDecode('\r\n') // returns "\r\n", doesn't lose the \r like other solutions.

如果你正在使用jQuery:

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

否则,使用Strictly Software的Encoder对象,它有一个很棒的htmlDecode()函数。