什么是HTML转义上下文?

dir*_*ide 8 html escaping

输出HTML时,有几个不同的地方可以将文本解释为控制字符而不是文本文字.例如,在"常规"文本中(即,在任何元素标记之外):

<div>This is regular text</div>
Run Code Online (Sandbox Code Playgroud)

以及属性值:

<input value="this is value text">
Run Code Online (Sandbox Code Playgroud)

并且,我相信,在HTML评论中:

<!-- This text here might be programmatically generated
and could, in theory, contain the double-hyphen character
sequence, which is verboten inside comments -->
Run Code Online (Sandbox Code Playgroud)

这三种文本中的每一种都有不同的规则,必须如何转义才能被视为非标记.所以我的第一个问题是,HTML中是否还有其他任何字符可以解释为标记/控制字符?上述情况显然对需要转义的内容有不同的规定.

第二个问题是,为了确保任何嵌入的文本被视为非标记,需要转义的规范的,全局安全的字符列表(对于每个上下文)是什么?例如,从理论上讲,您只需要在属性值中转义"和",因为在属性值中,只有结束分隔符('或"取决于属性值以哪个分隔符开头)具有控制含义.同样,在"常规"文本中只有<和&具有控制意义.(我意识到并非所有的HTML解析器都是相同的.我最感兴趣的是为了安抚符合规范的解析器而需要转义的最小字符集是什么.)

切向:以下文本将抛出错误,因为HTML 4.01严格:

<a href="http://example.com/file.php?x=1&y=2">foo</a>
Run Code Online (Sandbox Code Playgroud)

具体来说,它说它不知道实体"&y"应该是什么.如果你在&之后放置一个空格,那么它就可以正常验证.但是如果你在运行中生成它,你可能不想检查每次使用&是否会导致验证错误,而只是转义所有和内部属性值.

bob*_*nce 11

<div>This is regular text</div>
Run Code Online (Sandbox Code Playgroud)

文字内容:&必须转义.<必须逃脱.

如果使用非UTF编码生成文档,则必须转义不适合所选编码的字符.

在XHTML(和一般的XML)中,序列]]>不得出现在文本内容中,因此在该特定情况下,该序列中的一个字符必须被转义,传统上是>.为了保持一致性,Canonical XML规范选择>每次都在文本内容中转义,这对于转义函数来说并不是一个糟糕的策略,尽管你可以跳过它来进行手工创作.

<input value="this is value text">
Run Code Online (Sandbox Code Playgroud)

属性值:&必须转义.属性值分隔符"'必须进行转义.如果没有使用属性值分隔符(不要这样做),则不可能进行转义.

Canonical XML总是选择"作为分隔符,因此逃避它.该>字符并不需要在属性值进行转义和Canonical XML没有.HTML4规范建议编码>无论如何都是为了向后兼容,但是这只影响了现在没人记得的几个真正古老而可怕的浏览器; 你可以忽略它.

在XHTML中<必须进行转义.虽然你可以逃脱在HTML4中逃避它,但这不是一个好主意.

要在属性值中包含制表符,CR或LF(不通过属性值规范化算法将它们转换为普通空格),必须将它们编码为字符引用.

对于文本内容和属性值:在XML 1.1下的XHTML中,必须转义受限字符,即删除字符和C0和C1控制代码,减去制表符,CR,LF和NEL.总的来说,[\x01-\x08\x0B\x0C\x0E-\x1F\x7F-\x84\x86-\x9F].即使在XML 1.1中转义,也可能根本不包含空字符.在XML 1.1之外,你根本不能使用任何这些字符,也没有一个你想要的好理由.

<!-- This text here might be programmatically generated
and could, in theory, contain the double-hyphen character
sequence, which is verboten inside comments -->
Run Code Online (Sandbox Code Playgroud)

是的,但由于内部评论没有逃避,因此您无能为力.如果你写<!-- &lt; -->,它的字面意思是含有"&符号字母t-分号"的注释,并将在DOM或其​​他信息集中反映出来.包含的注释--根本无法序列化.

<![CDATA[<?piXML中的sections和s也不能使用转义.序列化包括序列的CDATA部分的传统解决方案]]>是将该序列分成两个CDATA部分,因此它不会一起出现.您无法在单个CDATA部分中对其进行序列化,也无法?>在数据中序列化PI .

像CDATA元素<script><style>用HTML(未XHTML)可以不包含</(ETAGO)序列仿佛后面没有结束标签的名称,这将早,然后错误结束的元素.由于在CDATA元素中不可能进行转义,因此必须避免和解决这个序列(例如,通过document.write('</p>')转入document.write('<\/p>');.(你会看到许多更复杂的愚蠢策略来解决这个问题,比如调用unescapeJS - % - 编码)字符串;甚至经常'</scr'+'ipt>'是无效的.)

在HTML和XML中还有一个上下文,其中适用不同的规则,并且在DTD中(包括DOCTYPE声明中的内部子集,如果有的话),其中%角色具有特殊权力并且需要转义才能使用从字面上.但作为一个HTML文档作者,你几乎不可能在任何接近整个混乱的地方.

The following text will throw errors as HTML 4.01 Strict:

<a href="http://example.com/file.php?x=1&y=2">foo</a>
Run Code Online (Sandbox Code Playgroud)

是的,这在Transitional中也是一个错误.

If you put a space after the &, however, it validates just fine. 
Run Code Online (Sandbox Code Playgroud)

是的,根据SGML规则,除了[A-Za-z]并且#不开始解析作为参考.尽管如此依靠这个并不是一个好主意.(当然,它在XHTML中不是很好.)