如何解码HTML实体使用jQuery?

我如何使用jQuery解码字符串中的HTML实体?

361811 次浏览

我认为你混淆了文本和HTML方法。看看这个例子,如果您使用元素的内部HTML作为文本,您将得到解码的HTML标记(第二个按钮)。但如果您将它们作为HTML使用,则会得到HTML格式的视图(第一个按钮)。

<div id="myDiv">
here is a <b>HTML</b> content.
</div>
<br />
<input value="Write as HTML" type="button" onclick="javascript:$('#resultDiv').html($('#myDiv').html());" />
&nbsp;&nbsp;
<input value="Write as Text" type="button" onclick="javascript:$('#resultDiv').text($('#myDiv').html());" />
<br /><br />
<div id="resultDiv">
Results here !
</div>

第一个按钮写着:在这里是一个超文本标记语言内容。

第二个按钮写着:这里是一个HTML</ b>内容。

顺便说一下,你可以看到我在jQuery plugin- HTML decode and encode中找到的一个插件,它编码和解码HTML字符串。

使用

myString = myString.replace( /\&amp;/g, '&' );

在服务器端最容易做到这一点,因为JavaScript显然没有用于处理实体的原生库,我也没有在搜索结果的顶部找到任何扩展JavaScript的框架。

搜索“JavaScript HTML实体”,你可能会找到一些用于此目的的库,但它们可能都是围绕上述逻辑构建的——逐个实体替换。

不使用jQuery:

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


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

它的工作原理类似于接受的答案,但用于不受信任的用户输入是安全的。


类似方法中的安全问题

Mike Samuel指出一样,使用带有不可信用户输入的<div>而不是<textarea>来执行此操作是XSS漏洞,即使<div>从未添加到DOM中:

function decodeEntities(encodedString) {
var div = document.createElement('div');
div.innerHTML = encodedString;
return div.textContent;
}


// Shows an alert
decodeEntities('<img src="nonexistent_image" onerror="alert(1337)">')

然而,这种攻击对<textarea>是不可能的,因为没有HTML元素是允许<textarea>的内容。因此,任何HTML标记仍然出现在'encoded'字符串中,浏览器将自动对其进行实体编码。

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


// Safe, and returns the correct answer
console.log(decodeEntities('<img src="nonexistent_image" onerror="alert(1337)">'))

警告:使用jQuery的.html().val()方法而不是使用.innerHTML.value来实现此功能也是不安全的*对于某些版本的jQuery, .val()0。这是因为旧版本的jQuery将.val()1包含在传递给.html()的字符串中。因此,在jQuery 1.8中,这样的代码显示了一个警告:

//<!-- CDATA
// Shows alert
$("<textarea>")
.html("<script>alert(1337);</script>")
.text();


//-->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.2.3/jquery.min.js"></script>

* Thanks to Eru Penkman for catching this vulnerability.

安全注意事项:使用这个答案(下面保留它的原始形式)可以在你的应用程序中引入XSS漏洞你不应该用这个答案。阅读lucascaro的回答来解释这个答案中的漏洞,并使用该答案或Mark Amery的回答是中的方法。

实际上,试一试

var encodedStr = "This is fun &amp; stuff";
var decoded = $("<div/>").html(encodedStr).text();
console.log(decoded);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div/>

我只是必须有一个HTML实体字符(⇓)作为一个HTML按钮的值。HTML代码在浏览器中从一开始就看起来很好:

<input type="button" value="Embed & Share  &dArr;" id="share_button" />

现在我添加了一个切换,也应该显示字符。这就是我的解

$("#share_button").toggle(
function(){
$("#share").slideDown();
$(this).attr("value", "Embed & Share " + $("<div>").html("&uArr;").text());
}

这显示⇓再次在按钮中。我希望这能帮助到一些人。

这个问题受到“用jQuery”的限制,但它可能会帮助一些人知道,在这里给出的最佳答案的jQuery代码下面做了以下工作…使用或不使用jQuery都可以:

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

使用jQuery解码HTML实体,只需使用这个函数:

function html_entity_decode(txt){
var randomID = Math.floor((Math.random()*100000)+1);
$('body').append('<div id="random'+randomID+'"></div>');
$('#random'+randomID).html(txt);
var entity_decoded = $('#random'+randomID).html();
$('#random'+randomID).remove();
return entity_decoded;
}

使用方法:

Javascript:

var txtEncoded = "&aacute; &eacute; &iacute; &oacute; &uacute;";
$('#some-id').val(html_entity_decode(txtEncoded));

HTML:

<input id="some-id" type="text" />

就像Mike Samuel说的,不要使用jQuery.html().text()来解码html实体,因为这是不安全的。

相反,使用模板渲染器,比如@VyvIT的注释中的Mustache.jsdecodeEntities

Underscore.js实用带库附带escapeunescape方法,但它们对用户输入不安全:

_.escape(string) .escape(string

_.unescape(string) .unescape(string

你必须为html实体定制函数:

function htmlEntities(str) {
return String(str).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g,'&gt;').replace(/"/g, '&quot;');
}

最简单的方法是为你的元素设置一个类选择器,然后使用以下代码:

$(function(){
$('.classSelector').each(function(a, b){
$(b).html($(b).text());
});
});

什么都不需要了!

我有这个问题,找到了这个清晰的解决方案,它工作得很好。

我认为这与我们选择的解决方案完全相反。

var decoded = $("<div/>").text(encodedStr).html();

可以使用库,该库可从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"

关于是否有任何理由在客户端代码中使用这个库来支持其他答案中提供的<textarea>黑客的问题,我图书馆的作者质疑道。他提供了一些可能的理由:

  • 如果你在服务器端使用node.js,使用HTML编码/解码库可以为你提供一个客户端和服务器端都能工作的解决方案。

  • 一些浏览器的实体解码算法有bug或缺少对某些命名字符引用的支持。例如,Internet Explorer将正确解码和呈现非间断空格(&nbsp;),但通过DOM元素的innerText属性将它们报告为普通空格,而不是非间断空格,从而打破了<textarea>黑客(尽管只是以一种较小的方式)。此外,ie8和ie9只是不支持 HTML 5中添加的任何新命名字符引用。的作者还在http://mathias.html5.org/tests/html/named-character-references/中主持了命名字符引用支持的测试。在IE 8中,它报告了一千多个错误。

    如果你想远离与实体解码相关的浏览器错误和/或能够处理全部范围的命名字符引用,你不能逃脱<textarea>黑客;你需要像这样的库。

  • 他只是觉得这样做事不那么俗气。

编码:

$("<textarea/>").html('<a>').html(); // return '&lt;a&gt'
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<textarea/>

解码:

$("<textarea/>").html('&lt;a&gt').val() // return '<a>'
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<textarea/>

假设下面有String。

我们的豪华客舱温暖舒适&舒适的

var str = $("p").text(); // get the text from <p> tag
$('p').html(str).text();  // Now,decode html entities in your variable i.e

STR和赋值回

标签。

就是这样。

对于ExtJS用户,如果你已经有了编码的字符串,例如当一个库函数的返回值是innerHTML内容时,考虑这个ExtJS函数:

Ext.util.Format.htmlDecode(innerHtmlContent)

扩展String类:

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

And use as method:

"&lt;img src='myimage.jpg'&gt;".decode()
这里还有一个问题: 转义字符串在分配给输入值

时看起来不可读
var string = _.escape("<img src=fake onerror=alert('boo!')>");
$('input').val(string);

简单:https://jsfiddle.net/kjpdwmqa/3/

或者,也有一个库。

在这里,https://cdnjs.com/libraries/he

npm install he                 //using node.js


<script src="js/he.js"></script>  //or from your javascript directory

用法如下…

//to encode text
he.encode('© Ande & Nonso® Company LImited 2018');


//to decode the
he.decode('&copy; Ande &amp; Nonso&reg; Company Limited 2018');

欢呼。

试试这个:

var htmlEntities = "&lt;script&gt;alert('hello');&lt;/script&gt;";
var htmlDecode =$.parseHTML(htmlEntities)[0]['wholeText'];
console.log(htmlDecode);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

parseHTML is a Function in Jquery library and it will return an array that includes some details about the given String..

in some cases the String is being big, so the function will separate the content to many indexes..

and to get all the indexes data you should go to any index, then access to the index called "wholeText".

I chose index 0 because it's will work in all cases (small String or big string).

您不需要jQuery来解决这个问题,因为它会产生一些开销和依赖。

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

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

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 (in case the text is big)
el.textContent = '';


return dec;
}


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

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