我知道XML的默认编码为UTF-8 。 所有的XML消费者一定要等等等等。 因此,这不仅是一个问题,XML是否有一个默认的编码。
我也知道, 在XML-Declarataion <?xml version="1.0" ... ?>
在文档的开头本身是可选的。 并且指定在其中的编码是可选的为好。
于是,我问自己,如果以下两个XML的声明是两个表达式为同样的事情:
<?xml version="1.0"?>
<?xml version="1.0" encoding="UTF-8"?>
从我自己目前的理解,我会说这些都是等价的,但我不知道 。 有以下两个声明的等价被指定的地方?
(请考虑下面两个例子是行每一个XML文档的第一行中,通过任何(零)个字节之前和为UTF-8编码)
简单的答案
在一个UTF-8编码的文件没有外部编码信息的非常特殊的情况(这是我从评论了解什么是你感兴趣的),有两个声明没有区别。
长的答案是更有趣,虽然。
什么是规范说
如果你看一下XML规范的附录F1 ,解释应遵循以确定编码时没有外部编码信息的过程。
如果文档被编码为UTF变体之一,解析器应该能够检测前4个字节中的编码,无论是从字节顺序标记,或XML声明的开始。
然而,根据该规范,它应该也看编码声明。
在上述情况下不需要读取编码声明,以确定编码,第4.3.3节仍需要编码声明,如果存在的话,可以读取和编码名称进行检查,以匹配实体的实际编码。
如果它们不匹配,根据4.3.3节 :
......它是为包括编码声明实体致命错误将被提交给XML处理器比中命名的其他编码
编码UTF-16,声明UTF-8
让我们看看当我们创建编码为UTF-16,但与编码声明设置为UTF-8的XML文档什么在现实中发生。
歌剧,Firefox和Chrome都解释文件为UTF-16,忽略编码声明。 的Internet Explorer(第9版至少),显示一个空白文档,但没有实际的错误。
所以,如果你在较后阶段你的UTF-8号文件和别人一个UTF-8编码声明将其转换为UTF-16,它会在大多数浏览器的工作,但在IE中失败(和,我想,大多数Microsoft XML蜜蜂)。 如果你已经离开了编码声明了,你会被罚款。
从技术上讲,我认为IE是最准确的。 作为这样的可以由该错误在编码电平,而不是XML水平出现的事实来解释:它不显示错误的事实。 据assumedly竭尽全力为UTF-16字符解释为UTF-8,未能找到解码任何字符,结束了传递一个空字符序列的XML解析器。
UTF-8编码,否则申报
现在你可能会认为火狐,Chrome和Opera都只是忽略编码声明干脆,但事实并非总是如此。
如果编码文件为UTF-8(字节顺序标记所以这是明确无误的作为其他东西),但编码声明设置为Latin1的,所有的浏览器都将成功解码的内容Latin1的,忽视了UTF-8 BOM。
同样,这似乎是我的权利。 该BOM字符非Latin1有效的事实只是意味着,他们都会被直接丢弃在字符解码水平。
这不适用于在UTF-8文档中的所有声明的编码工作,虽然。 如果申报的编码是UTF-16,我们又回到使用Opera,Firefox和Chrome忽略声明编码,而Internet Explorer中返回一个空白文档。
从本质上讲,任何让IE浏览器返回一个空白文档将会使其他浏览器忽略声明编码。
其他不一
另外值得一提的字节顺序标记的重要性。 根据该规范第4.3.3 :
在UTF-16必须编码实体[...]开始与字节顺序标记
但是,如果你尝试阅读没有BOM一个UTF-16编码XML文档,大多数浏览器将仍然接受它作为有效。 只有Firefox的报告将其作为XML解析错误。
外部编码信息
到现在为止,我们一直在考虑,当没有外部编码信息时会发生什么,但是,正如其他人所说,如果通过HTTP接收或封闭的文档中的某种形式的MIME信封,从这些来源的编码信息应接管文档编码偏好。
大多数的各种XML MIME类型的细节描述RFC3023 。 然而,现实的情况是从为指定的有所不同。
首先,与省略charset参数的文本/ XML应该使用US-ASCII的字符集,但这一要求几乎总是被忽略。 浏览器通常将使用XML编码声明,或默认的值,以UTF-8,如果有没有。
第二,如果存在对文档UTF-8 BOM,并且XML编码声明或者是UTF-8或不包括在内,该文件将被解释为UTF-8,而不管内容类型使用的字符集的。
从内容类型的编码似乎优先考虑的唯一时间是在没有BOM和明确的字符集的内容类型指定。
在任何情况下,不存在的情况下(涉及内容类型),其中包括关于UTF-8文档UTF-8编码的XML声明任何从没有在所有编码声明不同。
孤立地看 ,两者是等价的。 您已经引用这表明,这两种声明是等价的规范的相关部分。
然而XML可以有一个包络,诸如HTTP Content-Type
首部。 W3C的规定 ,这种信封信息在文件中的任何其他声明具有优先权。 因此,举例来说,如果你是通过HTTP检索XML,你可能会得到这样的:
HTTP/1.1 200 OK
Content-Type: text/xml
<root/>
在这种情况下,XML应该被理解为ASCII,因为默认字符集text/*
MIME类型是ASCII。 这就是为什么你应该使用application/xml
MIME类型-这些默认为UTF-8。 “应用程序”前缀是指相关应用规范定义的东西像默认编码。 (IE XML规范接管。)随着text/*
MIME类型,默认为ASCII码和charset
参数必须包含在MIME类型来更改字符集。
这里是另一种情况:
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
。
这不会是不合理的,如果它到达已经被检测为具有非兼容UTF-8编码(如UTF-16),一个文档的开始将被拒绝的第二个声明。 然而,鉴于你的声明,该文件是UTF-8编码,也没有什么区别,他们将如何处理 。
外部指定的编码将优先在这两种情况下; 这两份文件将仍然被同等对待。
我的阅读方式的规范 ,UTF-8是不是在XML声明中的默认编码。 只有默认的编码“为这既不字节顺序标记,也不是一个编码声明开头的实体”。 如果文档是UTF-16,具有BOM,它可能有一个XML声明没有编码声明或者XML声明的一切,仍然是有效的XML。
仅针对无BOM的文件,你提到的两个XML声明应该是等价的。