XML声明中的默认编码(UTF-8)的默认值如何?

时间:2013-05-03 14:57:48

标签: xml utf-8

我知道the default encoding of XML is UTF-8。所有XML消费者都必须等等。因此,这不仅仅是XML是否具有默认编码的问题。

我也知道文档开头的the XML-Declarataion <?xml version="1.0" ... ?>是可选的。而指定其中的编码也是可选的。

所以我问自己,以下两个XML声明是否是完全相同的两个表达式:

<?xml version="1.0"?>
<?xml version="1.0" encoding="UTF-8"?>

根据我自己目前的理解,我会说这些是等效的,但我不知道。 是否已在某处指定了这两个声明的等效性?

(考虑这两个示例行,每个行都是XML文档的第一行,前面是任意(零)字节,并且是UTF-8编码的)

4 个答案:

答案 0 :(得分:8)

简答

在没有外部编码信息的UTF-8编码文档的非常具体的情况下(我从评论中理解的是您感兴趣的内容),两个声明之间没有区别。

但答案很长很有趣。

规范的内容

如果查看Appendix F1 of the XML specification,则说明了在没有外部编码信息时确定编码时应遵循的过程。

如果文档被编码为UTF变体之一,则解析器应该能够检测前4个字节内的编码,可以是字节顺序标记,也可以是XML声明的开头。

但是,根据规范,它仍然应该读取编码声明。

  

在上述情况下,不需要读取编码声明来确定编码,4.3.3节仍然要求读取编码声明(如果存在),并检查编码名称以匹配实体的实际编码。

如果他们不匹配,根据section 4.3.3

  

...对于包含编码声明的实体而言,这是一个致命的错误,该编码声明将以非声明中的编码方式呈现给XML处理器

编码的UTF-16,声明为UTF-8

让我们看看当我们创建一个编码为UTF-16但编码声明设置为UTF-8的XML文档时会发生什么。

Opera,Firefox和Chrome都将该文档解释为UTF-16,忽略了编码声明。 Internet Explorer(至少版本9)显示空白文档,但没有实际错误。

因此,如果您在UTF-8文档中包含UTF-8编码声明,并且稍后某人将其转换为UTF-16,则它将在大多数浏览器中工作,但在IE中失败(并且,我假设,大多数Microsoft XML API)。如果您关闭了编码声明,那就没问题了。

从技术上讲,我认为IE是最准确的。它没有显示错误的事实可能是由于错误发生在编码级而不是XML级的事实。假设它正在尽力将UTF-16字符解释为UTF-8,未能找到任何解码的字符,并最终将空字符序列传递给XML解析器。

编码的UTF-8,否则声明为

您现在可能认为Firefox,Chrome和Opera完全忽略了编码声明,但情况并非如此。

如果您将文档编码为UTF-8(带有字节顺序标记,因此它可以像其他任何内容一样明确),但将编码声明设置为Latin1,则所有浏览器都会成功将内容解码为Latin1,忽略UTF-8 BOM。

这对我来说似乎也是对的。 BOM字符在Latin1中无效的事实只是意味着它们在字符解码级别被静默删除。

但这并不适用于UTF-8文档中所有已声明的编码。如果声明的编码是UTF-16,我们将重新使用Opera,Firefox和Chrome忽略声明的编码,而Internet Explorer会返回空白文档。

基本上,任何使IE返回空白文档的行为都会使其他浏览器忽略声明的编码。

其他不一致

还值得一提的是字节顺序标记的重要性。根据{{​​3}}:

  

以UTF-16编码的实体必须以字节顺序标记

开头

但是,如果您尝试在没有BOM的情况下读取UTF-16编码的XML文档,大多数浏览器仍会接受它为有效。只有Firefox将其报告为XML解析错误。

外部编码信息

到目前为止,我们一直在考虑在没有外部编码信息时会发生什么,但正如其他人所提到的那样,如果文档是通过HTTP接收的,或者是封装在某种类型的MIME信封中,那么编码来自这些来源的信息应优先于文件编码。

section 4.3.3 of the spec中描述了各种XML MIME类型的大部分细节。然而,现实与指定的有些不同。

首先,带有省略的charset参数的text / xml应该使用US-ASCII的字符集,但几乎总是忽略该要求。浏览器通常使用XML编码声明的值,如果没有,则默认为UTF-8。

其次,如果文档上有UTF-8 BOM,并且XML编码声明是UTF-8或不包括在内,则文档将被解释为UTF-8,而不管内容中使用的字符集是什么类型。

唯一一次来自Content-Type的编码似乎优先是没有BOM并且在Content-Type中指定了显式字符集。

在任何情况下,都没有案例(涉及Content-Type),其中UTF-8文档上包含UTF-8 XML编码声明与根本没有编码声明有任何不同。

答案 1 :(得分:6)

孤立地,两者都是等价的。您已经引用了规范的相关部分,这些部分表明两个声明都是等效的。

但是,XML可以有一个信封,例如HTTP Content-Type标头。 The W3C specifies此信封信息优先于文件中的任何其他声明。例如,如果您通过http检索XML,则可能会得到以下结果:

HTTP/1.1 200 OK
Content-Type: text/xml

<root/>

在这种情况下,XML应该被理解为 ascii ,因为text/* mime类型的默认字符集是ascii。这就是你应该使用application/xml mime类型的原因 - 这些默认为utf-8。 “application”前缀表示相关的应用程序规范定义了默认编码等内容。 (即XML规范接管。)对于text/* mime类型,默认为ascii,并且必须在mime类型中包含charset参数才能更改字符集。

这是另一个案例:

HTTP/1.1 200 OK
Content-Type: text/xml; charset=win-1252

<?xml version="1.0" encoding="utf-8"?>
<root/>

在这种情况下,符合标准的XML处理器应将此文件读为win-1252不是 utf-8

另一个案例:

HTTP/1.1 200 OK
Content-Type: application/xml

<?xml version="1.0" encoding="win-1252"?>
<root/>

此处编码为win-1252

HTTP/1.1 200 OK
Content-Type: application/xml; charset=ascii

<?xml version="1.0" encoding="win-1252"?>
<root/>

此处编码为ascii

答案 2 :(得分:5)

如果第二个声明到达已经被检测为具有非UTF-8兼容编码(例如UTF-16)的文档的开头,则拒绝第二个声明是不合理的。但是,鉴于您声明该文档采用UTF-8编码,how they would be treated之间没有区别。

外部指定的编码在两种情况下都优先;两份文件的处理方式仍然相同。

答案 3 :(得分:1)

我阅读the spec的方式,UTF-8 不是 XML声明中的默认编码。它只是默认编码“对于既不以字节顺序标记也不以编码声明开头的实体”。如果文档是UTF-16并且有一个BOM,它可能有一个没有编码声明的XML声明或根本没有XML声明,但仍然是有效的XML。

仅对于没有BOM的文档,您提到的两个XML声明应该是等效的。