HTML实体解码
如何使用JavaScript或JQuery对HTML实体进行编码和解码?
var varTitle = "Chris' corner";
我希望它是:
var varTitle = "Chris' corner";
你可以尝试像这样:
var Title = $('<textarea />').html("Chris' corner").text(); console.log(Title);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
我build议不要使用被接受的jQuery代码作为答案。 虽然它不会将string解码到页面中,但它确实会导致创build脚本和HTML元素等内容。 这是比我们需要更多的代码。 相反,我build议使用更安全,更优化的function。
var decodeEntities = (function() { // this prevents any overhead from creating the object each time var element = document.createElement('div'); function decodeHTMLEntities (str) { if(str && typeof str === 'string') { // strip script/html tags str = str.replace(/<script[^>]*>([\S\s]*?)<\/script>/gmi, ''); str = str.replace(/<\/?\w(?:[^"'>]|"[^"]*"|'[^']*')*>/gmi, ''); element.innerHTML = str; str = element.textContent; element.textContent = ''; } return str; } return decodeHTMLEntities; })();
要使用这个函数,只需调用decodeEntities("&")
,它将使用与jQuery版本相同的底层技术,但不包含jQuery的开销,并在input中清理HTML标签之后。 请参阅Mike Samuel对如何过滤HTML标签所接受的答案的评论 。
通过在您的项目中添加以下行,该函数可以很容易地用作jQuery插件。
jQuery.decodeEntities = decodeEntities;
像Robert K说的,不要使用jQuery.html()。text()解码html实体,因为它是不安全的,因为用户input永远不能访问DOM。 阅读XSS为什么这是不安全的。
而是尝试一下Underscore.js工具带库,它带有escape和unescape方法:
_.escape(串)
转义string以插入到HTML中,replace&
, <
, >
, "
, `
和'
字符。
_.escape('Curly, Larry & Moe'); => "Curly, Larry & Moe"
_.unescape(串)
与逃避相反,取代&
, <
, >
, "
, `
和'
与他们的非正式的同行。
_.unescape('Curly, Larry & Moe'); => "Curly, Larry & Moe"
要支持更多字符的解码,只需复制Underscore unescape方法并在地图中添加更多字符。
这里有一个不需要创builddiv的快速方法,并解码“最常见的”HTML转义字符:
function decodeHTMLEntities(text) { var entities = [ ['amp', '&'], ['apos', '\''], ['#x27', '\''], ['#x2F', '/'], ['#39', '\''], ['#47', '/'], ['lt', '<'], ['gt', '>'], ['nbsp', ' '], ['quot', '"'] ]; for (var i = 0, max = entities.length; i < max; ++i) text = text.replace(new RegExp('&'+entities[i][0]+';', 'g'), entities[i][1]); return text; }
受Robert K的解决scheme的启发,这个版本不去掉HTML标签,并且是安全的。
var decode_entities = (function() { // Remove HTML Entities var element = document.createElement('div'); function decode_HTML_entities (str) { if(str && typeof str === 'string') { // Escape HTML before decoding for HTML Entities str = escape(str).replace(/%26/g,'&').replace(/%23/g,'#').replace(/%3B/g,';'); element.innerHTML = str; if(element.innerText){ str = element.innerText; element.innerText = ''; }else{ // Firefox support str = element.textContent; element.textContent = ''; } } return unescape(str); } return decode_HTML_entities; })();
jQuery提供了一种对html实体进行编码和解码的方法。
如果你使用“<div />”标签,它会去掉所有的html。
function htmlDecode(value) { return $("<div/>").html(value).text(); } function htmlEncode(value) { return $('<div/>').text(value).html(); }
如果您使用“<textarea />”标记,它将保留html标记。
function htmlDecode(value) { return $("<textarea/>").html(value).text(); } function htmlEncode(value) { return $('<textarea/>').text(value).html(); }
在页面中注入不可信的HTML是非常危险的, 如何使用jQuery解码HTML实体? 。
另一种方法是使用PHP的html_entity_decode的JavaScript实现(来自http://phpjs.org/functions/html_entity_decode:424 )。 这个例子会是这样的:
var varTitle = html_entity_decode("Chris' corner");
受到Robert K的解决scheme的启发,剥离了html标签,并阻止执行脚本和事件处理程序,如: <img src=fake onerror="prompt(1)">
testing最新的Chrome,FF,IE(应该可以从IE9下工作, )。
var decodeEntities = (function () { //create a new html document (doesn't execute script tags in child elements) var doc = document.implementation.createHTMLDocument(""); var element = doc.createElement('div'); function getText(str) { element.innerHTML = str; str = element.textContent; element.textContent = ''; return str; } function decodeHTMLEntities(str) { if (str && typeof str === 'string') { var x = getText(str); while (str !== x) { str = x; x = getText(x); } return x; } } return decodeHTMLEntities; })();
只需致电:
decodeEntities('<img src=fake onerror="prompt(1)">'); decodeEntities("<script>alert('aaa!')</script>");
为了在列表中添加另一个“受Robert K启发”,这是另一个安全的版本, 它不去掉HTML标签 。 它不是通过HTMLparsing器来运行整个string,而是只提取实体并将其转换。
var decodeEntities = (function() { // this prevents any overhead from creating the object each time var element = document.createElement('div'); // regular expression matching HTML entities var entity = /&(?:#x[a-f0-9]+|#[0-9]+|[a-z0-9]+);?/ig; return function decodeHTMLEntities(str) { // find and replace all the html entities str = str.replace(entity, function(m) { element.innerHTML = m; return element.textContent; }); // reset the value element.textContent = ''; return str; } })();
这是一个完整的版本
function htmldecode(s){ window.HTML_ESC_MAP = { "nbsp":" ","iexcl":"¡","cent":"¢","pound":"£","curren":"¤","yen":"¥","brvbar":"¦","sect":"§","uml":"¨","copy":"©","ordf":"ª","laquo":"«","not":"¬","reg":"®","macr":"¯","deg":"°","plusmn":"±","sup2":"²","sup3":"³","acute":"´","micro":"µ","para":"¶","middot":"·","cedil":"¸","sup1":"¹","ordm":"º","raquo":"»","frac14":"¼","frac12":"½","frac34":"¾","iquest":"¿","Agrave":"À","Aacute":"Á","Acirc":"Â","Atilde":"Ã","Auml":"Ä","Aring":"Å","AElig":"Æ","Ccedil":"Ç","Egrave":"È","Eacute":"É","Ecirc":"Ê","Euml":"Ë","Igrave":"Ì","Iacute":"Í","Icirc":"Î","Iuml":"Ï","ETH":"Ð","Ntilde":"Ñ","Ograve":"Ò","Oacute":"Ó","Ocirc":"Ô","Otilde":"Õ","Ouml":"Ö","times":"×","Oslash":"Ø","Ugrave":"Ù","Uacute":"Ú","Ucirc":"Û","Uuml":"Ü","Yacute":"Ý","THORN":"Þ","szlig":"ß","agrave":"à","aacute":"á","acirc":"â","atilde":"ã","auml":"ä","aring":"å","aelig":"æ","ccedil":"ç","egrave":"è","eacute":"é","ecirc":"ê","euml":"ë","igrave":"ì","iacute":"í","icirc":"î","iuml":"ï","eth":"ð","ntilde":"ñ","ograve":"ò","oacute":"ó","ocirc":"ô","otilde":"õ","ouml":"ö","divide":"÷","oslash":"ø","ugrave":"ù","uacute":"ú","ucirc":"û","uuml":"ü","yacute":"ý","thorn":"þ","yuml":"ÿ","fnof":"ƒ","Alpha":"Α","Beta":"Β","Gamma":"Γ","Delta":"Δ","Epsilon":"Ε","Zeta":"Ζ","Eta":"Η","Theta":"Θ","Iota":"Ι","Kappa":"Κ","Lambda":"Λ","Mu":"Μ","Nu":"Ν","Xi":"Ξ","Omicron":"Ο","Pi":"Π","Rho":"Ρ","Sigma":"Σ","Tau":"Τ","Upsilon":"Υ","Phi":"Φ","Chi":"Χ","Psi":"Ψ","Omega":"Ω","alpha":"α","beta":"β","gamma":"γ","delta":"δ","epsilon":"ε","zeta":"ζ","eta":"η","theta":"θ","iota":"ι","kappa":"κ","lambda":"λ","mu":"μ","nu":"ν","xi":"ξ","omicron":"ο","pi":"π","rho":"ρ","sigmaf":"ς","sigma":"σ","tau":"τ","upsilon":"υ","phi":"φ","chi":"χ","psi":"ψ","omega":"ω","thetasym":"ϑ","upsih":"ϒ","piv":"ϖ","bull":"•","hellip":"…","prime":"′","Prime":"″","oline":"‾","frasl":"⁄","weierp":"℘","image":"ℑ","real":"ℜ","trade":"™","alefsym":"ℵ","larr":"←","uarr":"↑","rarr":"→","darr":"↓","harr":"↔","crarr":"↵","lArr":"⇐","uArr":"⇑","rArr":"⇒","dArr":"⇓","hArr":"⇔","forall":"∀","part":"∂","exist":"∃","empty":"∅","nabla":"∇","isin":"∈","notin":"∉","ni":"∋","prod":"∏","sum":"∑","minus":"−","lowast":"∗","radic":"√","prop":"∝","infin":"∞","ang":"∠","and":"∧","or":"∨","cap":"∩","cup":"∪","int":"∫","there4":"∴","sim":"∼","cong":"≅","asymp":"≈","ne":"≠","equiv":"≡","le":"≤","ge":"≥","sub":"⊂","sup":"⊃","nsub":"⊄","sube":"⊆","supe":"⊇","oplus":"⊕","otimes":"⊗","perp":"⊥","sdot":"⋅","lceil":"⌈","rceil":"⌉","lfloor":"⌊","rfloor":"⌋","lang":"〈","rang":"〉","loz":"◊","spades":"♠","clubs":"♣","hearts":"♥","diams":"♦","\"":"quot","amp":"&","lt":"<","gt":">","OElig":"Œ","oelig":"œ","Scaron":"Š","scaron":"š","Yuml":"Ÿ","circ":"ˆ","tilde":"˜","ndash":"–","mdash":"—","lsquo":"'","rsquo":"'","sbquo":"‚","ldquo":"“","rdquo":"”","bdquo":"„","dagger":"†","Dagger":"‡","permil":"‰","lsaquo":"‹","rsaquo":"›","euro":"€"}; if(!window.HTML_ESC_MAP_EXP) window.HTML_ESC_MAP_EXP = new RegExp("&("+Object.keys(HTML_ESC_MAP).join("|")+");","g"); return s?s.replace(window.HTML_ESC_MAP_EXP,function(x){ return HTML_ESC_MAP[x.substring(1,x.length-1)]||x; }):s; }
用法
htmldecode("∑ >€");
这是我最喜欢的HTML字符解码方式。 使用这个代码的好处是标签也被保留。
function decodeHtml(html) { var txt = document.createElement("textarea"); txt.innerHTML = html; return txt.value; }
例如: http : //jsfiddle.net/k65s3/
input:
Entity: Bad attempt at XSS:<script>alert('new\nline?')</script><br>
输出:
Entity: Bad attempt at XSS:<script>alert('new\nline?')</script><br>
我知道我已经晚了一点,但是我想我可能会提供下面的代码片段作为我如何使用jQuery来解码HTML实体的一个例子:
var varTitleE = "Chris' corner"; var varTitleD = $("<div/>").html(varTitleE).text(); console.log(varTitleE + " vs. " + varTitleD);
不要忘了启动您的检查员/萤火虫查看控制台结果 – 或者干脆更换console.log(…)w / alert(…)
这就是说,这是我的控制台通过谷歌Chrome检查员阅读:
Chris' corner vs. Chris' corner
因为@Robert K和@mattcasey都有很好的代码,所以我想我会在这里提供一个CoffeeScript版本,以防将来有人使用它:
String::unescape = (strict = false) -> ### # Take escaped text, and return the unescaped version # # @param string str | String to be used # @param bool strict | Stict mode will remove all HTML # # Test it here: # https://jsfiddle.net/tigerhawkvok/t9pn1dn5/ # # Code: https://gist.github.com/tigerhawkvok/285b8631ed6ebef4446d ### # Create a dummy element element = document.createElement("div") decodeHTMLEntities = (str) -> if str? and typeof str is "string" unless strict is true # escape HTML tags str = escape(str).replace(/%26/g,'&').replace(/%23/g,'#').replace(/%3B/g,';') else str = str.replace(/<script[^>]*>([\S\s]*?)<\/script>/gmi, '') str = str.replace(/<\/?\w(?:[^"'>]|"[^"]*"|'[^']*')*>/gmi, '') element.innerHTML = str if element.innerText # Do we support innerText? str = element.innerText element.innerText = "" else # Firefox str = element.textContent element.textContent = "" unescape(str) # Remove encoded or double-encoded tags fixHtmlEncodings = (string) -> string = string.replace(/\&#/mg, '&#') # The rest, for double-encodings string = string.replace(/\"/mg, '"') string = string.replace(/\"e;/mg, '"') string = string.replace(/\_/mg, '_') string = string.replace(/\'/mg, "'") string = string.replace(/\"/mg, '"') string = string.replace(/\>/mg, '>') string = string.replace(/\</mg, '<') string # Run it tmp = fixHtmlEncodings(this) decodeHTMLEntities(tmp)
请参阅https://jsfiddle.net/tigerhawkvok/t9pn1dn5/7/或https://gist.github.com/tigerhawkvok/285b8631ed6ebef4446d (包括编译的JS,并可能更新与此答案相比)
这里是另一个版本:
function convertHTMLEntity(text){ const span = document.createElement('span'); return text .replace(/&[#A-Za-z0-9]+;/gi, (entity,position,text)=> { span.innerHTML = entity; return span.innerText; }); } console.log(convertHTMLEntity('Large < £ 500'));
要做到这一点在没有jQuery的纯JavaScript或预定义的一切,你可以循环编码的htmlstring通过元素innerHTML和innerText(/ textContent)属性为每个解码步骤是必需的:
<html> <head> <title>For every decode step, cycle through innerHTML and innerText </title> <script> function decode(str) { var d = document.createElement("div"); d.innerHTML = str; return typeof d.innerText !== 'undefined' ? d.innerText : d.textContent; } </script> </head> <body> <script> var encodedString = "<p>name</p><p><span style=\"font-size:xx-small;\">ajde</span></p><p><em>da</em></p>"; </script> <input type=button onclick="document.body.innerHTML=decode(encodedString)"/> </body> </html>
你也问过如何对它们进行编码 – 你可以使用服务器端的function,或者你可以创build自己的对象来做映射,例如clj:一个用来转换扩展字符的函数?
我认为这与所选解决scheme完全相反。
var decoded = $("<div/>").text(encodedStr).html();
尝试一下 :)
@William Lahti的答案更实用一些:
var entities = { 'amp': '&', 'apos': '\'', '#x27': '\'', '#x2F': '/', '#39': '\'', '#47': '/', 'lt': '<', 'gt': '>', 'nbsp': ' ', 'quot': '"' } function decodeHTMLEntities (text) { return text.replace(/&([^;]+);/gm, function (match, entity) { return entities[entity] || match }) }