要在JavaScript中转义HTML实体?

2020/10/12 03:01 · javascript ·  · 0评论

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

还有什么其他方法可以诊断问题?

编辑:您应该按照Wladimir的建议使用DOMParser API ,因为发布的函数引入了安全漏洞,所以我编辑了以前的答案。

以下代码片段是旧答案的代码,但进行了少量修改:使用atextarea代替adiv可以减少XSS漏洞,但是在IE9和Firefox中仍然存在问题。

function htmlDecode(input){
  var e = document.createElement('textarea');
  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字符实体

编辑:此代码的旧版本不适用于带有空白输入的IE,如jsFiddle(在IE中查看)所示。上面的版本适用于所有输入。

更新:看来这不适用于大字符串,并且还引入了一个安全漏洞,请参阅注释。

此处给出的大多数答案都有一个很大的缺点:如果您不尝试转换的字符串不受信任,那么您最终将遇到跨站脚本(XSS)漏洞对于接受的答案中的功能,请考虑以下事项:

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

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

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

function htmlDecode(input) {
  var doc = new DOMParser().parseFromString(input, "text/html");
  return doc.documentElement.textContent;
}

console.log(  htmlDecode("&lt;img src='myimage.jpg'&gt;")  )    
// "<img src='myimage.jpg'>"

console.log(  htmlDecode("<img src='dummy' onerror='alert(/xss/)'>")  )  
// ""

保证此函数不会运行任何JavaScript代码。任何HTML标签都将被忽略,仅返回文本内容。

兼容性说明:解析HTMLDOMParser至少需要Chrome 30,Firefox 12,Opera 17,Internet Explorer 10,Safari 7.1或Microsoft Edge。因此,所有不支持浏览器的浏览器都已超过其EOL,并且截至2017年,偶尔仍然可以在野外看到的唯一浏览器是旧版Internet Explorer和Safari版本(通常这些浏览器还不多,令人不安)。

您需要解码所有编码的HTML实体还是仅对其&amp;本身进行解码

如果只需要处理,&amp;则可以执行以下操作:

var decoded = encoded.replace(/&amp;/g, '&');

如果您需要解码所有HTML实体,则可以不使用jQuery:

var elem = document.createElement('textarea');
elem.innerHTML = encoded;
var decoded = elem.value;

请注意下面Mark的注释,这些注释突出了此答案的早期版本中的安全漏洞,并建议使用textarea而不是div减轻潜在的XSS漏洞。无论您使用的是jQuery还是纯JavaScript,这些漏洞都存在。

用于从JavaScript解释HTML(文本和其他形式)的一个更现代的选项是DOMParserAPI中的HTML支持请参见MDN中的此处)。这使您可以使用浏览器的本机HTML解析器将字符串转换为HTML文档。自2014年底以来,所有主要浏览器的新版本均已支持该功能。

如果我们只想解码一些文本内容,则可以将其作为唯一的内容放入文档正文中,解析文档,然后将其拉出.body.textContent

var encodedStr = 'hello &amp; world';

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

console.log(decodedString);

我们可以在规范草案中DOMParser看到,已解析的文档未启用JavaScript,因此我们可以执行此文本转换而无需担心安全性。

parseFromString(str, type)方法必须运行以下步骤,具体取决于类型

  • "text/html"

    用an解析strHTML parser,并返回新创建的Document

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


    注意

    script元素被标记为不可执行,并且将其内容noscript解析为标记。

这超出了此问题的范围,但是请注意,如果您要获取解析的DOM节点本身(而不仅仅是它们的文本内容)并将其移至实时文档DOM,则可能会重新启用其脚本,并且可以出于安全考虑。我尚未对此进行研究,因此请谨慎行事。

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描述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漏洞。

如果您使用的是jQuery:

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

否则,使用严格的软件的编码对象,其拥有出色的htmlDecode()功能。

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

element.innerText 也能解决问题。

您可以使用Lodash unescape /转义功能https://lodash.com/docs/4.17.5#unescape

import unescape from 'lodash/unescape';

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

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

如果您像我一样在寻找它,那么这里有一个不错且安全的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。

诀窍是利用浏览器的功能来解码特殊的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
    });
}

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>

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

首先<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

不是直接回答您的问题,但是让RPC在结构中返回带有这些图像数据(示例中的网址)的某个结构(XML或JSON或其他)会更好吗?

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

您从RPC收到的结构如下所示:

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

我认为这样比较好,因为将来自外部源的代码注入您的页面看起来不太安全。想象有人劫持了您的XML-RPC脚本,并在其中放了您不想要的东西(甚至是一些javascript ...)

克里斯(Chris)的回答很好,很优雅,但是如果值未定义,答案就会失败只需简单的改进就可以使其变得可靠:

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

捕获常见问题的javascript解决方案:

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

这是https://stackoverflow.com/a/4835406/2738039的反面

对于单线球员:

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

这个问题并没有指明来源,x但是如果可以的话,可以防御恶意(或者来自我们自己的应用程序的意外)输入是有意义的。例如,假设x值为&amp; <script>alert('hello');</script>在jQuery中处理此问题的一种安全简单的方法是:

var x    = "&amp; <script>alert('hello');</script>";
var safe = $('<div />').html(x).text();

// => "& alert('hello');"

通过https://gist.github.com/jmblog/3222899找到我看不出有什么理由避免使用此解决方案,因为它至少与某些替代方案一样短,甚至不短,并且可以防御XSS。

(我最初将其发布为评论,但由于在同一主题中的后续评论要求我这样做,因此将其添加为答案)。

我尝试了一切从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;", "&"));

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

我非常疯狂,无法完成这个功能,即使不是很完整,也应该很详尽:

function removeEncoding(string) {
    return string.replace(/&Agrave;/g, "À").replace(/&Aacute;/g, "Á").replace(/&Acirc;/g, "Â").replace(/&Atilde;/g, "Ã").replace(/&Auml;/g, "Ä").replace(/&Aring;/g, "Å").replace(/&agrave;/g, "à").replace(/&acirc;/g, "â").replace(/&atilde;/g, "ã").replace(/&auml;/g, "ä").replace(/&aring;/g, "å").replace(/&AElig;/g, "Æ").replace(/&aelig;/g, "æ").replace(/&szlig;/g, "ß").replace(/&Ccedil;/g, "Ç").replace(/&ccedil;/g, "ç").replace(/&Egrave;/g, "È").replace(/&Eacute;/g, "É").replace(/&Ecirc;/g, "Ê").replace(/&Euml;/g, "Ë").replace(/&egrave;/g, "è").replace(/&eacute;/g, "é").replace(/&ecirc;/g, "ê").replace(/&euml;/g, "ë").replace(/&#131;/g, "ƒ").replace(/&Igrave;/g, "Ì").replace(/&Iacute;/g, "Í").replace(/&Icirc;/g, "Î").replace(/&Iuml;/g, "Ï").replace(/&igrave;/g, "ì").replace(/&iacute;/g, "í").replace(/&icirc;/g, "î").replace(/&iuml;/g, "ï").replace(/&Ntilde;/g, "Ñ").replace(/&ntilde;/g, "ñ").replace(/&Ograve;/g, "Ò").replace(/&Oacute;/g, "Ó").replace(/&Ocirc;/g, "Ô").replace(/&Otilde;/g, "Õ").replace(/&Ouml;/g, "Ö").replace(/&ograve;/g, "ò").replace(/&oacute;/g, "ó").replace(/&ocirc;/g, "ô").replace(/&otilde;/g, "õ").replace(/&ouml;/g, "ö").replace(/&Oslash;/g, "Ø").replace(/&oslash;/g, "ø").replace(/&#140;/g, "Œ").replace(/&#156;/g, "œ").replace(/&#138;/g, "Š").replace(/&#154;/g, "š").replace(/&Ugrave;/g, "Ù").replace(/&Uacute;/g, "Ú").replace(/&Ucirc;/g, "Û").replace(/&Uuml;/g, "Ü").replace(/&ugrave;/g, "ù").replace(/&uacute;/g, "ú").replace(/&ucirc;/g, "û").replace(/&uuml;/g, "ü").replace(/&#181;/g, "µ").replace(/&#215;/g, "×").replace(/&Yacute;/g, "Ý").replace(/&#159;/g, "Ÿ").replace(/&yacute;/g, "ý").replace(/&yuml;/g, "ÿ").replace(/&#176;/g, "°").replace(/&#134;/g, "†").replace(/&#135;/g, "‡").replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&#177;/g, "±").replace(/&#171;/g, "«").replace(/&#187;/g, "»").replace(/&#191;/g, "¿").replace(/&#161;/g, "¡").replace(/&#183;/g, "·").replace(/&#149;/g, "•").replace(/&#153;/g, "™").replace(/&copy;/g, "©").replace(/&reg;/g, "®").replace(/&#167;/g, "§").replace(/&#182;/g, "¶").replace(/&Alpha;/g, "Α").replace(/&Beta;/g, "Β").replace(/&Gamma;/g, "Γ").replace(/&Delta;/g, "Δ").replace(/&Epsilon;/g, "Ε").replace(/&Zeta;/g, "Ζ").replace(/&Eta;/g, "Η").replace(/&Theta;/g, "Θ").replace(/&Iota;/g, "Ι").replace(/&Kappa;/g, "Κ").replace(/&Lambda;/g, "Λ").replace(/&Mu;/g, "Μ").replace(/&Nu;/g, "Ν").replace(/&Xi;/g, "Ξ").replace(/&Omicron;/g, "Ο").replace(/&Pi;/g, "Π").replace(/&Rho;/g, "Ρ").replace(/&Sigma;/g, "Σ").replace(/&Tau;/g, "Τ").replace(/&Upsilon;/g, "Υ").replace(/&Phi;/g, "Φ").replace(/&Chi;/g, "Χ").replace(/&Psi;/g, "Ψ").replace(/&Omega;/g, "Ω").replace(/&alpha;/g, "α").replace(/&beta;/g, "β").replace(/&gamma;/g, "γ").replace(/&delta;/g, "δ").replace(/&epsilon;/g, "ε").replace(/&zeta;/g, "ζ").replace(/&eta;/g, "η").replace(/&theta;/g, "θ").replace(/&iota;/g, "ι").replace(/&kappa;/g, "κ").replace(/&lambda;/g, "λ").replace(/&mu;/g, "μ").replace(/&nu;/g, "ν").replace(/&xi;/g, "ξ").replace(/&omicron;/g, "ο").replace(/&piρ;/g, "ρ").replace(/&rho;/g, "ς").replace(/&sigmaf;/g, "ς").replace(/&sigma;/g, "σ").replace(/&tau;/g, "τ").replace(/&phi;/g, "φ").replace(/&chi;/g, "χ").replace(/&psi;/g, "ψ").replace(/&omega;/g, "ω").replace(/&bull;/g, "•").replace(/&hellip;/g, "…").replace(/&prime;/g, "′").replace(/&Prime;/g, "″").replace(/&oline;/g, "‾").replace(/&frasl;/g, "⁄").replace(/&weierp;/g, "℘").replace(/&image;/g, "ℑ").replace(/&real;/g, "ℜ").replace(/&trade;/g, "™").replace(/&alefsym;/g, "ℵ").replace(/&larr;/g, "←").replace(/&uarr;/g, "↑").replace(/&rarr;/g, "→").replace(/&darr;/g, "↓").replace(/&barr;/g, "↔").replace(/&crarr;/g, "↵").replace(/&lArr;/g, "⇐").replace(/&uArr;/g, "⇑").replace(/&rArr;/g, "⇒").replace(/&dArr;/g, "⇓").replace(/&hArr;/g, "⇔").replace(/&forall;/g, "∀").replace(/&part;/g, "∂").replace(/&exist;/g, "∃").replace(/&empty;/g, "∅").replace(/&nabla;/g, "∇").replace(/&isin;/g, "∈").replace(/&notin;/g, "∉").replace(/&ni;/g, "∋").replace(/&prod;/g, "∏").replace(/&sum;/g, "∑").replace(/&minus;/g, "−").replace(/&lowast;/g, "∗").replace(/&radic;/g, "√").replace(/&prop;/g, "∝").replace(/&infin;/g, "∞").replace(/&OEig;/g, "Œ").replace(/&oelig;/g, "œ").replace(/&Yuml;/g, "Ÿ").replace(/&spades;/g, "♠").replace(/&clubs;/g, "♣").replace(/&hearts;/g, "♥").replace(/&diams;/g, "♦").replace(/&thetasym;/g, "ϑ").replace(/&upsih;/g, "ϒ").replace(/&piv;/g, "ϖ").replace(/&Scaron;/g, "Š").replace(/&scaron;/g, "š").replace(/&ang;/g, "∠").replace(/&and;/g, "∧").replace(/&or;/g, "∨").replace(/&cap;/g, "∩").replace(/&cup;/g, "∪").replace(/&int;/g, "∫").replace(/&there4;/g, "∴").replace(/&sim;/g, "∼").replace(/&cong;/g, "≅").replace(/&asymp;/g, "≈").replace(/&ne;/g, "≠").replace(/&equiv;/g, "≡").replace(/&le;/g, "≤").replace(/&ge;/g, "≥").replace(/&sub;/g, "⊂").replace(/&sup;/g, "⊃").replace(/&nsub;/g, "⊄").replace(/&sube;/g, "⊆").replace(/&supe;/g, "⊇").replace(/&oplus;/g, "⊕").replace(/&otimes;/g, "⊗").replace(/&perp;/g, "⊥").replace(/&sdot;/g, "⋅").replace(/&lcell;/g, "⌈").replace(/&rcell;/g, "⌉").replace(/&lfloor;/g, "⌊").replace(/&rfloor;/g, "⌋").replace(/&lang;/g, "⟨").replace(/&rang;/g, "⟩").replace(/&loz;/g, "◊").replace(/&#039;/g, "'").replace(/&amp;/g, "&").replace(/&quot;/g, "\"");
}

像这样使用:

let decodedText = removeEncoding("Ich hei&szlig;e David");
console.log(decodedText);

印刷品: Ich Heiße David

PS这花了一个半小时的时间。

这是到目前为止我尝试过的最全面的解决方案:

const STANDARD_HTML_ENTITIES = {
    nbsp: String.fromCharCode(160),
    amp: "&",
    quot: '"',
    lt: "<",
    gt: ">"
};

const replaceHtmlEntities = plainTextString => {
    return plainTextString
        .replace(/&#(\d+);/g, (match, dec) => String.fromCharCode(dec))
        .replace(
            /&(nbsp|amp|quot|lt|gt);/g,
            (a, b) => STANDARD_HTML_ENTITIES[b]
        );
};

要对JavaScript中的HTML实体*进行转义,可以使用小型库html-escapernpm install html-escaper

import {unescape} from 'html-escaper';

unescape('escaped string');

或者unescape从功能Lodash下划线,如果你正在使用它。


*)请注意,这些功能并不能覆盖所有的HTML实体,而只是最常见的,即&<>'"要取消转义所有HTML实体,你可以使用自己的库。

我在项目中使用了此方法:受其他答案的启发,但具有额外的安全参数,在处理修饰字符时可能很有用

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

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

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.
var encodedStr = 'hello &amp; world';

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

console.log(decodedString);
function decodeHTMLContent(htmlText) {
  var txt = document.createElement("span");
  txt.innerHTML = htmlText;
  return txt.innerText;
}

var result = decodeHTMLContent('One &amp; two &amp; three');
console.log(result);

有一个变种,其效率高达最高答案的80%。

请参阅基准:https : //jsperf.com/decode-html12345678/1

性能测试

console.log(decodeEntities('test: &gt'));

function decodeEntities(str) {
  // this prevents any overhead from creating the object each time
  const el = decodeEntities.element || document.createElement('textarea')

  // strip script/html tags
  el.innerHTML = str
    .replace(/<script[^>]*>([\S\s]*?)<\/script>/gmi, '')
    .replace(/<\/?\w(?:[^"'>]|"[^"]*"|'[^']*')*>/gmi, '');

  return el.value;
}

如果需要离开标签,则删除两个.replace(...)调用(如果不需要脚本,可以离开第一个)。

本文地址:http://javascript.askforanswer.com/yaozaijavascriptzhongzhuanyihtmlshiti.html
文章标签: ,   ,   ,  
版权声明:本文为原创文章,版权归 javascript 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!