在使用Javascript时如何转义HTML5数据属性中的引号

37

我正在使用jQuery的.data()函数,用于处理自定义HTML5数据属性,其中属性值需要能够包含单引号和双引号:

<p class="example" data-example="She said "WTF" on last night's show.">

我知道在 data 属性值中使用像 &quot; 这样的字符编码可以使上述内容正常工作,但我不能总是控制值的输入方式。此外,我需要能够在标记中使用 HTML 标签,例如:

<p class="example" data-example="
She said "<abbr title="What The F***">WTF</abbr>" on last night's show.
">
如果某种形式的 .replace() 是答案,那么需要在值被 .data() 读取之前完成——也许可以将它应用于整个 <body> 中?常规的反斜杠转义(例如 <abbr title="te\'st">WTF</abbr>)也不起作用。理想情况下,这应该具有适用于以下两种情况的灵活性:data-example="..."data-example='...',但如果只能够以一种方式实现,那我至少可以接受。有什么好的建议吗? 更新 - 更多背景:我正在为 responsejs.com 进行这项工作。实际应用可能是仅在宽度大于某个特定值的浏览器中加载侧边栏(并在浏览器中处理,而不是在 PHP 中处理)。例如,在 WordPress 中,侧边栏可以包含小部件、图片等。PHP 标记内的引号不是问题,因为它们在到达浏览器之前会被解析为 HTML。例如:
<aside id="primary" class="sidebar" 

        data-oweb=' 

            <?php dynamic_sidebar( 'primary' ); ?>

        '
    >

    optional default markup for mobile and no-js browsers here

</aside>

1
JavaScript 无法在页面渲染后帮助您修复标签的引号。必须在服务器端完成。 - epascarello
11个回答

37

无论如何,您都必须适当地转义值,否则HTML将无法正确解析。您不能在解析后使用Javascript来纠正代码,因为此时已经发生了错误。

使用适当的HTML编码,您的示例将如下所示:

<p class="example" data-example="She said &quot;&lt;abbr title=&quot;What The F***&quot;&gt;WTF&lt;/abbr&gt;&quot; on last night's show.">

您不能使用反斜杠转义字符,因为它不是Javascript代码。在HTML代码中,您需要使用HTML实体来转义字符。

如果您无法控制数据输入的方式,那么您就很麻烦了。您只需找到一种方法来掌控它。


12
使用 htmlspecialchars() 函数和选项 ENT_QUOTES 将其打印出来,例如 <?php echo(htmlspecialchars($myValue,ENT_QUOTES)) ?>。有关更多信息,请访问:http://php.net/manual/en/function.htmlspecialchars.php。 - Roy Shoa

9
使用encodeURI来转义JSON对象中的引号。使用decodeURI解析字符串。

var popup = document.getElementById('popup'),
    msgObj = JSON.parse(decodeURI(popup.dataset.message));

console.log(msgObj);
<a id="popup" href="#" data-message="%7B%22title%22:%22Print%22,%22message%22:%22Printing%20not%20yet%20implemented%22%7D" />


2
相当简洁的解决方案。 - Ezequias Lopes
2
低估的解决方案 - 这个非常好地解决了问题。 - daggett

4

当我需要在PHP和JavaScript之间传输一些数据时,我使用了data属性并将其与html元素一起传输。在后端,我只需对数据使用base64_encode进行编码,在客户端使用 base64Decode(input)进行解码以获取数据。这样做可以避免任何转义混乱。我的JavaScript代码放在这里http://www.webtoolkit.info/


3
如果必须使用带有"'等内容的HTML字符串,为什么不为它们创建单独的HTML元素:http://jsfiddle.net/N7XXu/

例如,HTML代码:

<p class="example" data-which="1">a</p>

<p class="example-data" data-which="1">She said "<abbr title="What The F***">WTF</abbr>" on last night's show.</p>

与以下JavaScript结合使用:
$('.example').each(function() {
    var correspondingElem = $('.example-data[data-which="'
                              + $(this).data('which')
                              + '"]');
    $(this).data('example', correspondingElem.html());
});

alert($('.example').data('example'));

当然,隐藏.example-data元素。

谢谢,这很酷,但对于我需要的东西来说行不通。我刚刚更新了问题并提供了更多背景信息。 - ryanve

2

你尝试使用单引号来表示你的数据了吗?

像这样:

<p class="example" data-example='She said "WTF" on last night's show.'>

2

这是我创建的一个简单工具,可以用来编码HTML:

诀窍是要进行两次转义。

我添加了一个额外的 \n 替换来保留多行文本,因为它会被text()丢弃。

此外,您需要转义引号,以使其对数据属性安全。

<div id="esc"></div>
<textarea id="escinput" placeholder="Enter text"></textarea>
<script>
    $("#escinput").bind("change paste keyup", function(){
        $("#esc").text($(this).val().replace(/\n/g,'\\n'));
        $("#esc").text($("#esc").html().replace(/"/g, '&quot;'));
    });            
</script>

这应该创建一个数据属性安全字符串。

你可以在这里测试:http://jsfiddle.net/SplicePHP/n6HFq/

要将其解码回html,只需使用:

<script>
    var attr = $("#idOfElement").data('attribute');
    var decoded = $('<textarea/>').html(attr).val();
</script>

2
要使它成为正确的html,您必须转义这些麻烦的字符。我会用HTML实体来转义它们。这意味着输入此信息的工具必须正确地存储它们,或者检索它们的后端工具必须对它们进行转义。
然后,如果您想在JS中使用它们,您需要运行一些查找和替换函数将字符转换回HTML和引号。
大多数后端开发语言都有某种“htmlescape / unescape”功能,因此不应该太难。
要通过jQuery取消转义,请使用通过快速Google发现的以下内容:http://www.naveen.com.au/javascript/jquery/encode-or-decode-html-entities-with-jquery/289

3
需要将编码的字符替换回来吗?当通过JavaScript访问属性值时,它已经被规范化为纯文本了。 - shesek

0

正如此答案所建议的那样,这里有一个可能的解决方案:

var popup = $('#placeholder');
popup.html(`
<div data-message="${encodeURI("i could be what ever you need \' \" i will escape ! ")}" >
</div>
`);

console.log(decodeURI(popup.find('div').data("message")));
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div id="placeholder">
</div>

重点在于:
wierdText = decodeURI(someText))

和:

someText = encodeURI(wierdText)

反转函数是可以保存任何字符串的,而不会被解释为HTML或HTML属性,因为它用于内联href标记,它就是为了完成这个工作而设计的。


-1
如果您正在使用 Lodash,那么您可以使用 _.escape()_.unescape()。它将字符串中的字符 "&", "<", ">", '"', 和 "'" 转换为相应的 HTML 实体。
参考: https://lodash.com/docs/#escape

-1

这有点棘手,但你可以通过它们包含单引号的data属性选择dom对象。诀窍是\\'

<div id="text" data-message="Stanley Kubrick's Oranges">Hello</div>

<script>
    var message = "Stanley Kubrick\\'s Oranges";
    $("#text[data-message='"+message+"']").fadeOut("slow");
</script>

小提琴


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接