一个有效的XML文件是否需要XML声明?

135
我正在使用Xerces的Sax解析器解析一个XML文件。 XML声明<?xml version="1.0" encoding="UTF-8"?>是否是必需的?

3
有效和格式良好的文件是有区别的。你指的是哪一个? - Felix Kling
我收到了Prolog错误/无效的UTF-8编码。然后我发现XML文件中有BOM,用户使用记事本打开了该文件(我无法避免这种情况)。我不确定我是否在引用有效或格式良好的文档。只需要避免错误,因此我正在创建一个函数,删除“<”之前的所有字节。我需要确保XML头声明是必需的。你们认为呢? - eros
有没有一个Java类可以从InputStream中删除BOM或XML文件中的几个字节?我在考虑使用FilterInputStream和PushbackInputStream中的skip方法,但不知道如何使用它。 - eros
@eros: “我不确定我是否在引用有效或格式良好的文档。”请参阅格式良好与有效的XML以获得有关差异的简明解释。 - kjhughes
3个回答

201
在XML 1.0中,XML声明可选的。请参见XML 1.0推荐文档的2.8节,其中表示应该使用它-这意味着它是建议性的,但不是强制性的。然而,在XML 1.1中,声明是强制性的。请参见XML 1.1推荐文档的2.8节,其中表示必须使用它。它还进一步说明,如果缺少声明,则自动意味着该文档为XML 1.0文档。
请注意,在XML声明中,encodingstandalone都是可选的。只有version是必需的。此外,它们不是属性,因此,如果它们存在,则必须按照以下顺序排列:version,后跟任何encoding,后跟任何standalone
<?xml version="1.0"?>
<?xml version="1.0" encoding="UTF-8"?>
<?xml version="1.0" standalone="yes"?>
<?xml version="1.0" encoding="UTF-16" standalone="yes"?>
如果您不以这种方式指定编码,XML解析器将尝试猜测使用的编码方式。 XML 1.0建议书描述了一种可能的字符编码自动检测方法。实际上,如果输入以UTF-8、UTF-16或US-ASCII编码,这并不是什么大问题。当遇到使用US-ASCII范围之外的字符(例如ISO 8859-1)的8位编码时,自动检测就无法正常工作 - 如果可以避免创建这些编码,则应该避免。 standalone表示XML文档在没有DTD的情况下能否被正确处理。人们很少使用它。现在,设计一个XML格式,缺少其DTD中的信息是不好的。
更新:
“prolog error / invalid utf-8 encoding”错误表示解析器在文件内找到的实际数据与XML声明中指定的编码不匹配。或者在某些情况下,文件内的数据与自动检测到的编码不匹配。
由于您的文件包含字节顺序标记(BOM),因此应以UTF-16编码。我怀疑您的声明说<?xml version =“1.0”encoding =“ UTF-8”?>,这显然是不正确的,因为文件已被NotePad更改为UTF-16。简单的解决方案是删除encoding并仅写<?xml version =“1.0”?>。您也可以将其编辑为encoding =“UTF-16”,但对于原始文件(不在UTF-16中)或如果文件以某种方式被更改回UTF-8或其他编码,则这将是错误的。
不要费力去除BOM - 这不是问题的原因。使用NotePad或WordPad编辑XML才是真正的问题!

我的问题得到了回答,但我的后续问题没有得到解答。我需要再创建一个问题吗?还是请在这里添加它。 - eros
5
BOM可能是问题的原因。一些较旧的XML解析器不接受UTF-8文档开头的BOM(它是为UTF-16设计的,只有在后来使用UTF-8时才变得可接受)。但如果您使用的是最新版本的Xerces,则不太可能会出现问题。 - Michael Kay
还要注意,在记事本的“另存为”对话框中,您可以选择要将XML保存为哪种编码方式。如果您想删除BOM,请选择“ASCII”进行保存(假设您没有使用任何Unicode字符)。对于低于127个字符的内容,ASCII和UTF-8是相同的。 - BrainSlugs83

9

XML声明是可选的,所以没有它你的XML也可以是格式良好的。但建议使用它,以免解析器对所使用的编码做出错误的假设。


3
我是唯一一个觉得很奇怪的人吗?你在XML解析器已经开始解码文档后才告诉它使用什么编码方式。我的意思是,如果它可以解析那个标签并理解它的含义,那么它已经找到了正确的编码方式。我想不出任何合法使用编码属性的情况。 - BrainSlugs83
2
在没有BOM的情况下,编码被指定为8位。因此,可以是ASCII、UTF-8或任何旧的8位国家编码中的一种。XML声明全部都是8位的低半部分,这在所有这些编码中都是相等的,并传达足够的信息以选择高半部分。虽然不是最好的设计,但仍然比像以前的文本文件中常见的在CP1241和CP866之间猜测要好。 - Eugene Ryabtsev
但是他们应该干净利落地说XML是UTF-8 - 故事结束。 - Lothar

5

只有在您没有使用默认值 versionencoding 时才需要此步骤(在该示例中您已经使用了这些默认值)。


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