如何阻止HTML TEXTAREA解码HTML实体

27

我遇到了一个奇怪的问题:

在数据库中,我有一个字面上的“ampersand lt semicolon”:

<div  
每当它被打印到HTML textarea标签时,页面的源代码就会将>显示为>。 我该怎么停止这种解码?
答案:无法停止解码,因为浏览器会自动将HTML实体编码解码为它们所代表的字符。如果您想在textarea中显示原始文本,请使用JavaScript或其他编程语言对其进行编码。

你是如何打印输出的?在页面源代码中它是什么样子的? - Oded
你使用过 html_entity_decode() 函数吗? - Sonal Khunt
什么语言?什么平台? - Oded
可能是重复的问题:为什么<textarea>显示<>而不是<>? - Lukas Eder
7个回答

41
你无法阻止文本框中实体的解码,因为文本框的内容不是 (与脚本或样式元素不同) 内在的 CDATA。尽管错误恢复有时会给人一种这样的印象,但实际上并非如此。

文本框元素的定义如下:

<!ELEMENT TEXTAREA - - (#PCDATA)       -- multi-line text field -->

i.e. 它包含 PCDATA,被描述为

文档文本(由 SGML 结构“#PCDATA”表示)。文本可能包含字符引用。请记住,它们以 & 开始,并以分号结束(例如,Herg&eacute;'s adventures of Tintin 包含 e acute 字符的字符实体引用)。

这意味着当您键入(无效HTML的)“开始标记”(<)时,浏览器会将其更正为“小于号”(&lt;),但是当您键入“实体开始”(&)时,这是允许的,不会发生错误校正。

您需要写出您的意思。如果要将某些 HTML 包含为数据,则必须将任何具有特殊含义的字符转换为其相应的字符引用。

如果数据为:

&lt;div

然后HTML必须是:

<textarea>&amp;lt;div</textarea>

你可以使用标准函数进行转换(例如PHP的htmlspecialchars或Perl的HTML::Entities模块)。
注意1:如果您正在使用XHTML[2](并且确实在使用它,如果以text/html格式提供则不算),则可以使用显式CDATA块。
<textarea><![CDATA[&lt;div]]></textarea>

NB 2:或者如果浏览器正确实现了HTML 4


好的,但问题是。为什么它还是解码它们?假设我添加了&,保存文本区域,它将被保存为&lt;,但显示为<,再次保存将把它转换回<(但在数据库中仍然是<),再次保存将在数据库中保存为<,为什么文本区域会解码它?

  • 服务器发送(给浏览器)编码为HTML的数据。
  • 浏览器发送(给服务器)编码为application/x-www-form-urlencoded(或multipart/form-data)的数据。

由于浏览器未将数据作为HTML发送,因此字符未表示为HTML实体。

如果您将从客户端接收到的数据放入HTML文档中,则必须首先将其编码为HTML。


25
在PHP中,可以使用htmlentities()函数来实现这一点。以下是示例。
<?php
  $content = "This string contains the TM symbol: &trade;";
  print "<textarea>". htmlentities($content) ."</textarea>";
?>

如果没有使用htmlentities(),文本框会将商标符号(™)解释为"&trade;"并显示出来。

http://php.net/manual/zh/function.htmlentities.php


好的是,在表单提交后甚至不需要转换回来,因为浏览器会解码 htmlentities - Moradnejad

1

是的!使用 element.value 而不是直接填充 HTML 可以解决问题。 - csr-nontol

1

你必须确保这被渲染到浏览器中:

<textarea name="somename">&amp;lt;div</textarea>

基本上,这意味着在 &lt; 中的 & 必须进行 HTML 编码为 &amp;。如何实现取决于您使用的技术。

更新:可以这样理解。如果您想在文本区域中 显示 <div>,则必须对 <> 进行编码,否则 <div> 将成为浏览器中的普通 HTML 元素:

<textarea name="somename">&lt;div&gt;</textarea>

话虽如此,如果你想在文本框中显示<div>,你需要再次对&进行编码,因为浏览器在渲染HTML时会解码HTML实体,这与你的数据库无关。


1
好的,但问题是为什么它仍然解码它们呢?假设我已经添加了&,保存文本区域,它将被保存为&lt;,但显示为<,再次保存将重新转换为<(但在数据库中仍然为&lt;),再次保存将以<保存到数据库中,为什么文本区域会对其进行解码? - Rami Dabain
1
浏览器根据HTML标准进行解码。如果在<textarea/>之外显示,它仍将被解码。因此,您必须将&编码为浏览器,而不是数据库。换个角度想一想。如果您想向浏览器(无论是文本区域还是其他地方)显示一个<div>,您该如何做到不对<>进行编码,而是直接显示呢?您无法这样做,因为<div>将被解释为HTML元素。现在,递归思考一下。如果不对&进行编码,您该如何在浏览器中显示&lt;div&gt;...? - Lukas Eder
如果您查看页面的源代码,它会显示为&lt;,但在浏览器中它会被解码为<!我知道这是不可能的,但确实发生了,我对此非常确定。 - Rami Dabain
1
@RonanDejhero:现在有两个有趣的解释来回答你的问题,但是剩下的思考工作,恐怕只能由你自己来完成了……除非你拒绝理解事物是如何运作的 :-) - Lukas Eder
1
@Ronan Dejhero — 这并不是不可能的,这是 HTML 规范所要求发生的。 - Quentin
显示剩余2条评论

0

我找到了一种替代方案,可以在浏览器中读取和处理数据。只需使用jQuery读取元素的text(),它会返回显示字符,并允许我通过html()属性从textarea写入到div的innerHTML中...


0

我曾经遇到过同样的问题,解决方法是在将文本放入文本区域之前,在数据库中进行了两次替换:

myString = Replace(myString, "&", "&amp;")
myString = Replace(myString, "<", "&lt;")

替换 n:o 1 来欺骗文本框显示代码。替换 n:o 2:如果没有这个替换,你无法在文本框中显示 "" 字符(它会结束文本框标记)。

(上面是 Asp / vbscript 代码,请将其翻译为您所选择的语言中的替换方法)


-1

只用JS和HTML...

...用一个最简单的例子回答实际问题:

<textarea id=myta></textarea>

<script id=mytext type=text/plain>
  &trade;
</script>

<script>  myta.value = mytext.innerText;  </script>

解释:

脚本标签不会呈现HTML或实体。通过将文本存储在脚本标签中,它将保持原样——问题是它将尝试作为JavaScript执行。因此,我们使用一个空的文本区域并将文本存储在脚本标签中(这里是第一个标签)。

为了防止这种情况发生,我们将MIME类型更改为text/plain,而不是默认的text/javascript。这将防止其运行。

然后,为了填充文本区域,我们将脚本标签的内容复制到其中(这里在第二个脚本标签中完成)。

我发现唯一的注意事项是您必须使用JavaScript,并且不能直接在其中包含脚本标签。


谁给我点了踩,请解释一下。正如我所解释的那样,这是最纯粹的答案,因为在HTML文件中,您无法直接将HTML实体存储在文本区域中而不会在页面加载时被预渲染,而这个答案是唯一没有依赖关系的答案。因此,它是最简单的解决方案。 - jdmayfield

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