XML解析器对空白字符的处理取决于内容模型、xml:space属性及解析器策略;默认执行规范化(换行缩进变空格、压缩多空、首尾剥离),仅mixed content或xml:space="preserve"可保留原始空白。

XML解析器对空白字符的处理取决于这些空白是否出现在元素内容中,以及元素是否被声明为mixed content(混合内容)或具有特定的xml:space属性。换行和缩进本身不是语法错误,但是否保留、忽略或规范化,由上下文和解析器策略共同决定。
默认情况下:空白可能被“规范化”或“忽略”
根据XML 1.0规范,解析器在读取标记内容(character data)时,会执行空白规范化(whitespace normalization):
- 将所有制表符(
\t)、回车(\r)、换行(\n)统一视为空格字符(); - 将连续多个空白字符(包括换行缩进)压缩为单个空格;
- 开头和结尾的空白会被剥离(trim),除非该元素被定义为preserved whitespace。
这种行为只适用于element content(即元素标签之间的纯文本,且该元素在DTD或Schema中被声明为仅含子元素、不含混合文本)。例如:
<para>Hello world
</para>
默认解析后,文本内容通常变成"Hello world"(首尾去空、中间多空变一空)。
如何保留换行和缩进:使用xml:space="preserve"
可在任意元素上显式声明xml:space="preserve",告诉解析器:该元素及其所有后代中的所有空白字符(包括换行、缩进、多个空格)都应原样保留。
- 这是W3C标准支持的机制,无需依赖特定解析器扩展;
- 常用于
<pre>、<code>、<textarea>类语义的XML元素; - 例如:
<code xml:space="preserve"> a = 1;\n b = 2;</code>,解析后仍含原始缩进与换行。
Schema/DTD影响:内容模型决定空白是否“有意义”
如果一个元素在DTD或XML Schema中被定义为EMPTY或element-only(如<!ELEMENT para (em|strong)*>),那么其中出现的纯文本(包括换行缩进)属于“意外字符数据”,解析器通常会将其视为ignorable whitespace并直接丢弃。
- 只有当元素允许mixed content(如
<!ELEMENT para (#PCDATA|em|strong)*>)时,内部的换行缩进才可能作为#PCDATA的一部分被保留(但仍受上述规范化规则约束,除非加xml:space); - 现代Schema语言(如XSD)中,可通过
whiteSpacefacet(值为preserve、replace或collapse)进一步控制具体文本字段的处理方式。
实际开发中的建议
不要依赖格式化空白“自动保留”。若需可靠控制:
- 对需要原样展示的内容,显式添加
xml:space="preserve"; - 避免在结构型元素(如
<book><title>)内混入无意义的换行缩进,以免不同解析器行为不一致; - 使用DOM/SAX等API时,注意其默认配置:某些库(如Java的DocumentBuilder)默认忽略可忽略空白,需调用
setIgnoringElementContentWhitespace(false)才能获取全部文本节点; - 调试时可用
isWhitespaceInElementContent()(DOM Level 3)等方法判断某文本节点是否仅为规范化的空白。
基本上就这些。核心是:XML不把换行缩进当语法成分,是否保留,得看内容模型+显式声明+解析器设置。










