我有一些与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/
诊断这个问题的其他方法是什么?
var htmlEnDeCode = (function() {
var charToEntityRegex,
entityToCharRegex,
charToEntity,
entityToChar;
function resetCharacterEntities() {
charToEntity = {};
entityToChar = {};
// add the default set
addCharacterEntities({
'&' : '&',
'>' : '>',
'<' : '<',
'"' : '"',
''' : "'"
});
}
function addCharacterEntities(newEntities) {
var charKeys = [],
entityKeys = [],
key, echar;
for (key in newEntities) {
echar = newEntities[key];
entityToChar[key] = echar;
charToEntity[echar] = key;
charKeys.push(echar);
entityKeys.push(key);
}
charToEntityRegex = new RegExp('(' + charKeys.join('|') + ')', 'g');
entityToCharRegex = new RegExp('(' + entityKeys.join('|') + '|&#[0-9]{1,5};' + ')', 'g');
}
function htmlEncode(value){
var htmlEncodeReplaceFn = function(match, capture) {
return charToEntity[capture];
};
return (!value) ? value : String(value).replace(charToEntityRegex, htmlEncodeReplaceFn);
}
function htmlDecode(value) {
var htmlDecodeReplaceFn = function(match, capture) {
return (capture in entityToChar) ? entityToChar[capture] : String.fromCharCode(parseInt(capture.substr(2), 10));
};
return (!value) ? value : String(value).replace(entityToCharRegex, htmlDecodeReplaceFn);
}
resetCharacterEntities();
return {
htmlEncode: htmlEncode,
htmlDecode: htmlDecode
};
})();
这是ExtJS的源代码。
CMS的答案很好,除非你想要取消转义的HTML非常长,超过65536个字符。因为在Chrome中,内部HTML被分割成许多子节点,每个子节点最长65536个,你需要将它们连接起来。这个函数也适用于很长的字符串:
function unencodeHtmlContent(escapedHtml) {
var elem = document.createElement('div');
elem.innerHTML = escapedHtml;
var result = '';
// Chrome splits innerHTML into many child nodes, each one at most 65536.
// Whereas FF creates just one single huge child node.
for (var i = 0; i < elem.childNodes.length; ++i) {
result = result + elem.childNodes[i].nodeValue;
}
return result;
}
有关innerHTML最大长度的更多信息,请参阅以下答案:https://stackoverflow.com/a/27545633/694469
你需要解码所有编码的HTML实体或只是&本身?
如果你只需要处理&然后你可以这样做:
var decoded = encoded.replace(/&/g, '&');
如果你需要解码所有HTML实体,那么你可以不使用jQuery:
var elem = document.createElement('textarea');
elem.innerHTML = encoded;
var decoded = elem.value;
请注意下面Mark的评论,他强调了这个答案早期版本中的安全漏洞,并建议使用textarea而不是div来减轻潜在的XSS漏洞。无论使用jQuery还是纯JavaScript,这些漏洞都存在。
首先创建一个<span id="decodeIt" style="display:none;></span>在身体某处
接下来,将要解码为innerHTML的字符串赋值如下:
document.getElementById("decodeIt").innerHTML=stringtodecode
最后,
stringtodecode=document.getElementById("decodeIt").innerText
下面是整个代码:
var stringtodecode="<B>Hello</B> world<br>";
document.getElementById("decodeIt").innerHTML=stringtodecode;
stringtodecode=document.getElementById("decodeIt").innerText
Matthias Bynens有一个这样的库:https://github.com/mathiasbynens/he
例子:
console.log(
he.decode("Jörg & Jürgen rocked to & 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 & 2')); // '1 & 2'
但是请注意安全问题,影响类似的方法,我在链接的答案中列出!这种方法是一种hack,将来对文本区域允许内容的更改(或特定浏览器中的错误)可能会导致依赖它的代码有一天突然出现XSS漏洞。