首页 文章

在Javascript中使用Unescape HTML实体?

提问于
浏览
114

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

诊断问题的其他方法有哪些?

10 回答

  • 4

    我使用以下方法:

    function htmlDecode(input){
      var e = document.createElement('div');
      e.innerHTML = input;
      // handle case of empty input
      return e.childNodes.length === 0 ? "" : e.childNodes[0].nodeValue;
    }
    
    htmlDecode("&lt;img src='myimage.jpg'&gt;"); 
    // returns "<img src='myimage.jpg'>"
    

    基本上我以编程方式创建DOM元素,将编码的HTML分配给其innerHTML,并从innerHTML插入中创建的文本节点中检索nodeValue . 由于它只是创建一个元素但从未添加它,因此不会修改任何网站HTML .

    它将跨浏览器(包括旧版浏览器)工作并接受所有HTML Character Entities .

    编辑:此代码的旧版本不适用于具有空白输入的IE,如证据here on jsFiddle(在IE中查看) . 上述版本适用于所有输入 .

    更新:看起来这不适用于大字符串,它还引入了 security vulnerability ,请参阅注释 .

  • 1

    这里给出的大多数答案都有一个很大的缺点:如果您尝试转换的字符串不受信任,那么您最终会得到Cross-Site Scripting (XSS) vulnerability . 对于accepted answer中的功能,请考虑以下事项:

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

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

    使用all modern browsers支持的DOMParser可以避免这种情况:

    function htmlDecode(input)
    {
      var doc = new DOMParser().parseFromString(input, "text/html");
      return doc.documentElement.textContent;
    }
    
    // This returns "<img src='myimage.jpg'>"
    htmlDecode("&lt;img src='myimage.jpg'&gt;");
    
    // This returns ""
    htmlDecode("<img src='dummy' onerror='alert(/xss/)'>");
    

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

    兼容性说明:使用_1516385解析HTML至少需要Chrome 30,Firefox 12,Opera 17,Internet Explorer 10,Safari 7.1或Microsoft Edge . 因此,所有没有支持的浏览器都会超过他们的EOL,而截至2017年,唯一仍然可以在野外看到的浏览器偶尔会出现旧的Internet Explorer和Safari版本(通常这些版本仍然不足以打扰) .

  • 152

    如果你正在使用jQuery:

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

    否则,请使用Strictly Software's Encoder Object,它具有出色的 htmlDecode() 功能 .

  • 0

    诀窍是使用浏览器的强大功能来解码特殊的HTML字符,但不允许浏览器执行结果,就好像它是真正的html ...这个函数使用正则表达式来识别和替换编码的HTML字符,一个字符一次 .

    function unescapeHtml(html) {
        var el = document.createElement('div');
        return html.replace(/\&[#0-9a-z]+;/gi, function (enc) {
            el.innerHTML = enc;
            return el.innerText
        });
    }
    
  • 4

    克里斯的回答是美好而优雅的,但如果未定义值,则会失败 . 只需简单的改进即可:

    function htmlDecode(value) {
       return (typeof value === 'undefined') ? '' : $('<div/>').html(value).text();
    }
    
  • 6

    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

  • 39

    不是对您的问题的直接回应,但是对于您的RPC在该结构中返回某些结构(无论是XML还是JSON或其他)与这些图像数据(示例中的URL)不是更好吗?

    然后你可以在你的javascript中解析它并使用javascript本身构建 <img> .

    您从RPC接收的结构可能如下所示:

    {"img" : ["myimage.jpg", "myimage2.jpg"]}
    

    我认为这样做更好,因为将来自外部源的代码注入到您的页面中看起来并不安全 . 成像某人劫持您的XML-RPC脚本并放置您不想要的东西(甚至是一些javascript ...)

  • 3

    这是更好的:

    String::decode = ->
       $('<textarea />').html(this).text()
    

    使用:

    "&lt;img src='myimage.jpg'&gt;".decode();
    

    来自:HTML Entity Decode

  • 0

    我在我的项目中使用它:受other answers启发,但有一个额外的安全参数,在处理装饰字符时很有用

    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>';
    
  • 219

    这里所有其他答案都有问题 .

    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专门用于避免executig 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.
    

相关问题