我有一些与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/

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


当前回答

我知道这里有很多好的答案,但由于我实现了一个有点不同的方法,我想分享一下。

这段代码是一种非常安全的安全方法,因为转义处理程序依赖于浏览器,而不是函数。因此,如果将来发现新的漏洞,将覆盖此解决方案。

const decodeHTMLEntities = text => {
    // Create a new element or use one from cache, to save some element creation overhead
    const el = decodeHTMLEntities.__cache_data_element 
             = decodeHTMLEntities.__cache_data_element 
               || document.createElement('div');
    
    const enc = text
        // Prevent any mixup of existing pattern in text
        .replace(/⪪/g, '⪪#')
        // Encode entities in special format. This will prevent native element encoder to replace any amp characters
        .replace(/&([a-z1-8]{2,31}|#x[0-9a-f]+|#\d+);/gi, '⪪$1⪫');

    // Encode any HTML tags in the text to prevent script injection
    el.textContent = enc;

    // Decode entities from special format, back to their original HTML entities format
    el.innerHTML = el.innerHTML
        .replace(/⪪([a-z1-8]{2,31}|#x[0-9a-f]+|#\d+)⪫/gi, '&$1;')
        .replace(/#⪫/g, '⪫');
   
    // Get the decoded HTML entities
    const dec = el.textContent;
    
    // Clear the element content, in order to preserve a bit of memory (it is just the text may be pretty big)
    el.textContent = '';

    return dec;
}

// Example
console.log(decodeHTMLEntities("<script>alert('&awconint;&CounterClockwiseContourIntegral;&#x02233;&#8755;⪪#x02233⪫');</script>"));
// Prints: <script>alert('∳∳∳∳⪪##x02233⪫');</script>

顺便说一下,我选择使用字符⪪和⪫,因为它们很少被使用,因此通过匹配它们影响性能的几率显著降低。

其他回答

对于只说一句话的男人:

const htmlDecode = innerHTML => Object.assign(document.createElement('textarea'), {innerHTML}).value;

console.log(htmlDecode('Complicated - Dimitri Vegas &amp; Like Mike'));

不客气只是一个信使……全部归功于ourcodeworld.com,链接如下。

window.htmlentities = {
        /**
         * Converts a string to its html characters completely.
         *
         * @param {String} str String with unescaped HTML characters
         **/
        encode : function(str) {
            var buf = [];

            for (var i=str.length-1;i>=0;i--) {
                buf.unshift(['&#', str[i].charCodeAt(), ';'].join(''));
            }

            return buf.join('');
        },
        /**
         * Converts an html characterSet into its original character.
         *
         * @param {String} str htmlSet entities
         **/
        decode : function(str) {
            return str.replace(/&#(\d+);/g, function(match, dec) {
                return String.fromCharCode(dec);
            });
        }
    };

出处:https://ourcodeworld.com/articles/read/188/encode-and-decode-html-entities-using-pure-javascript

我在我的项目中使用了这个方法:受到其他答案的启发,但有一个额外的安全参数,在处理装饰字符时很有用

var decodeEntities=(function(){

    var el=document.createElement('div');
    return function(str, safeEscape){

        if(str && typeof str === 'string'){

            str=str.replace(/\</g, '&lt;');

            el.innerHTML=str;
            if(el.innerText){

                str=el.innerText;
                el.innerText='';
            }
            else if(el.textContent){

                str=el.textContent;
                el.textContent='';
            }

            if(safeEscape)
                str=str.replace(/\</g, '&lt;');
        }
        return str;
    }
})();

它的可用性如下:

var label='safe <b> character &eacute;ntity</b>';
var safehtml='<div title="'+decodeEntities(label)+'">'+decodeEntities(label, true)+'</div>';

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

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

有一种变体的效率是最高层的答案的80%。

参见基准测试:https://jsperf.com/decode-html12345678/1

console.log (decodeEntities('测试:在')); 函数decodeEntities(str) { //这将避免每次创建对象时产生任何开销 const el = decodeEntities。document.createElement('textarea') //条带脚本/html标签 埃尔。innerHTML = str .replace(/ <脚本(^ >]* > ([\ S \ S] * ?) < > \ /脚本/ gmi公司”) .replace (/ < \ / ? \ w (?:[^"'>]|"[^"]*"|'[^']*')*>/ gmi公司”); 返回el.value; }

如果需要留下标记,那么删除两个.replace(…)调用(如果不需要脚本,可以留下第一个调用)。