解码&回到&在JavaScript中

时间:2010-09-13 12:24:10

标签: javascript html text decode

我有像

这样的字符串
var str = 'One & two & three';

由Web服务器呈现为HTML。我需要将这些字符串转换为

'One & two & three'

目前,这就是我正在做的事情(借助jQuery):

$(document.createElement('div')).html('{{ driver.person.name }}').text()

然而,我有一种不安的感觉,我做错了。 我试过了

unescape("&")

但它似乎不起作用,也不是decodeURI / decodeURIComponent。

还有其他更原始,更优雅的方法吗?

12 个答案:

答案 0 :(得分:262)

您是否需要解码所有已编码的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,都存在这些漏洞。

答案 1 :(得分:73)

用于从JavaScript解释HTML(文本和其他)的更现代的选项是DOMParser API(see here in MDN)中的HTML支持。这允许您使用浏览器的本机HTML解析器将字符串转换为HTML文档。自2014年底以来,它已在所有主流浏览器的新版本中得到支持。

如果我们只想解码一些文本内容,我们可以将其作为文档正文中的唯一内容,解析文档,并提取其.body.textContent

var encodedStr = 'hello & world';

var parser = new DOMParser;
var dom = parser.parseFromString(
    '<!doctype html><body>' + encodedStr,
    'text/html');
var decodedString = dom.body.textContent;

console.log(decodedString);

我们可以在the draft specification for DOMParser中看到未针对已解析的文档启用JavaScript,因此我们可以在没有安全问题的情况下执行此文本转换。

  

parseFromString(str, type)方法必须运行这些步骤,具体取决于 type

     
      
  • "text/html"

         

    使用HTML parser解析 str ,并返回新创建的Document

         

    脚本标志必须设置为“禁用”。

         
        注意          

    script个元素标记为不可执行,noscript的内容被解析为标记。

      
  •   

这超出了这个问题的范围,但是请注意如果您自己处理解析的DOM节点(不仅仅是文本内容)并将它们移动到实时文档DOM,那么它可能他们的脚本将被重新启用,并且可能存在安全问题。我没有研究过,所以请谨慎行事。

答案 2 :(得分:37)

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机会。

如果您真的无法忍受加载到库中,可以使用this answer中描述的textarea hack来解决一个近似重复的问题,这与已建议的各种类似方法不同,我没有安全漏洞:

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

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

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

答案 3 :(得分:23)

var htmlEnDeCode = (function() {
    var charToEntityRegex,
        entityToCharRegex,
        charToEntity,
        entityToChar;

    function resetCharacterEntities() {
        charToEntity = {};
        entityToChar = {};
        // add the default set
        addCharacterEntities({
            '&amp;'     :   '&',
            '&gt;'      :   '>',
            '&lt;'      :   '<',
            '&quot;'    :   '"',
            '&#39;'     :   "'"
        });
    }

    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的源代码。

答案 4 :(得分:14)

element.innerText也可以解决问题。

答案 5 :(得分:8)

如果您正在寻找它,就像我一样 - 同时还有一个不错且安全的JQuery方法。

https://api.jquery.com/jquery.parsehtml/

你可以f.ex.在您的控制台中输入:

var x = "test &amp;";
> undefined
$.parseHTML(x)[0].textContent
> "test &"

所以$ .parseHTML(x)返回一个数组,如果你的文本中有HTML标记,则array.length将大于1。

答案 6 :(得分:6)

jQuery将为您编码和解码。但是,您需要使用textarea标记,而不是div。

var str1 = 'One & two & three';
var str2 = "One &amp; two &amp; three";
  
$(document).ready(function() {
   $("#encoded").text(htmlEncode(str1)); 
   $("#decoded").text(htmlDecode(str2));
});

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>

<div id="encoded"></div>
<div id="decoded"></div>

答案 7 :(得分:6)

您可以使用Lodash unescape / escape function https://lodash.com/docs/4.17.5#unescape

import unescape from 'lodash/unescape';

const str = unescape('fred, barney, &amp; pebbles');

str将成为'fred, barney, & pebbles'

答案 8 :(得分:3)

首先在身体的某处创建一个<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

答案 9 :(得分:2)

对于一线人:

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

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

答案 10 :(得分:1)

抓住常见问题的JavaScript解决方案:

var map = {amp: '&', lt: '<', gt: '>', quot: '"', '#039': "'"}
str = str.replace(/&([^;]+);/g, (m, c) => map[c])

这与https://stackoverflow.com/a/4835406/2738039

相反

答案 11 :(得分:0)

我尽一切努力从JSON数组中删除&。以上示例都不是,但是https://stackoverflow.com/users/2030321/chris提供了一个很好的解决方案,使我得以解决问题。

var stringtodecode="<B>Hello</B> world<br>";
document.getElementById("decodeIt").innerHTML=stringtodecode;
stringtodecode=document.getElementById("decodeIt").innerText

我没有使用,因为我不知道如何将其插入到将JSON数据拉入数组的模式窗口中,但是我确实根据示例进行了尝试,并且有效:

var modal = document.getElementById('demodal');
$('#ampersandcontent').text(replaceAll(data[0],"&amp;", "&"));

我喜欢它,因为它很简单并且可以使用,但是不确定为什么它没有被广泛使用。上下搜索以查找简单的解决方案。 我继续寻求对语法的理解,以及是否有使用此语法的风险。尚未发现任何东西。