乐途乐途
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
    • HTTP协议
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • MyBatis
    • Spring
    • Spring MVC
    • Maven 入门
    • Maven 进阶
    • Java 设计模式
  • 缓存

    • Redis
联系
阿里云
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
    • HTTP协议
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • MyBatis
    • Spring
    • Spring MVC
    • Maven 入门
    • Maven 进阶
    • Java 设计模式
  • 缓存

    • Redis
联系
阿里云
  • 学习路径
  • XML 基础语法

    • XML 概述
    • XML 文档结构
    • XML 元素
    • XML 属性
    • XML 语法规则
    • XML 命名空间
    • XML 注释与处理指令
  • DTD 与文档验证

    • DTD 概述
    • DTD 元素声明
    • DTD 属性声明
    • DTD 实体声明
    • DTD 元素与属性对比
    • DTD 完整示例
  • XML Schema 定义

    • XML Schema 概述
    • XSD 简单类型
    • XSD 复杂类型
    • XSD 命名空间与引用
  • XPath 节点定位

    • XPath 概述
    • XPath 路径表达式
    • XPath 谓词与函数
  • XSLT 转换

    • XSLT 概述
    • XSLT 模板与匹配
    • XSLT 控制结构
    • XSLT 输出控制
  • XML 解析技术

    • XML 解析概述
    • DOM 解析
    • SAX 解析
    • StAX 解析
    • XML 与 Java — JAXP
  • XML 在 Java 中的应用

    • Spring XML 配置
    • MyBatis XML 映射
    • pom.xml 与 Maven
    • web.xml 配置详解
  • 现代数据格式对比

    • XML 与 JSON 对比
    • XML 与 YAML 对比
  • XML 显示与浏览器集成

    • XML 在浏览器中的显示
    • XMLHttpRequest 与 AJAX
    • 服务器端 XML 处理
  • XML 进阶查询与链接

    • XQuery 查询语言
    • XLink 超链接
    • XML 验证工具使用
  • XML Web 服务(选读)

    • XML Web 服务概述
    • SOAP 协议详解
    • WSDL 服务描述
    • RSS 内容聚合
    • RDF 资源描述框架

XML 语法规则

本章定位 :掌握 XML 的五项铁律语法规则——违反任何一条都会导致 XML 解析器报 fatal error 并拒绝处理整个文档。这是 XML 与 HTML 最大的行为差异。

定义与作用

XML 的语法规则是其最核心的约束。与 HTML 的"尽力渲染"策略不同,XML 采用"要么全对,要么全错"的严格策略——任何语法错误都会导致解析器立即停止并报 fatal error 。这种设计哲学源于 XML 的第一个设计目标:"处理 XML 的程序应易于编写"——严格的语法让解析器无需处理各种容错分支,代码更简单可靠。

这套语法规则的另一个重要作用是 保证数据完整性 。在系统间传输数据时,如果接收方收到的 XML 格式良好,就可以放心解析;如果格式有误,就会明确报错而非默默吞掉数据。

核心原理:XML 解析器的处理流程

图解释 :XML 解析器按顺序检查五项规则。任何一项失败都直接报 fatal error。这与 HTML 浏览器的容错机制形成鲜明对比——HTML 即使嵌套错误也试图渲染,XML 直接拒绝处理。

语法/结构要点

五项核心语法规则

序号规则正确示例错误示例
1所有元素必须有关闭标签<p>文本</p> 或 <br/><p>文本
2标签大小写敏感<Note>...</Note><Note>...</note>
3元素必须正确嵌套<b><i>文本</i></b><b><i>文本</b></i>
4属性值必须加引号<note date="2024/01/01"><note date=2024/01/01>
5必须有且只有一个根元素<root>...</root> 包裹所有两个顶层元素并排

5 个预定义实体引用

XML 中 < 和 & 是保留字符,必须用实体引用转义:

字符实体引用说明
<&lt;小于号(less than)
>&gt;大于号(greater than)
&&amp;与符号(ampersand)
'&apos;单引号(apostrophe)
"&quot;双引号(quotation)

CDATA 段

当文本包含大量特殊字符(如代码片段),逐个转义很繁琐。<![CDATA[...]]> 内的文本被解析器 原样保留 :

<code>
<![CDATA[
if (a < b && b > c) {
    System.out.println("a < b < c is false");
}
]]>
</code>

CDATA 段的规则:

  • 不能包含 ]]>(这表示 CDATA 结束)
  • 不能嵌套 CDATA 段
  • CDATA 内的 &lt; 不会被解析为 <——所有内容都是字面量

完整示例:小崔发现"幽灵数据"事件

场景说明

飞翔科技技术部的后端开发 小崔 最近接手了实习生写的一个 XML 配置文件。程序在服务器上运行时一切正常,但在他的开发机上解析报错。小崔百思不得其解——"同样的 XML 文件,为什么线上可以,本地不行?"

操作前:有问题的 XML

<?xml version="1.0" encoding="UTF-8"?>
<servers>
  <server id="web01">
    <name>乐途官网站点</name>
    <ip>192.168.1.100</ip>
    <port>8080</port>
  <server id="db01">
    <name>主数据库</name>
    <ip>192.168.1.200</ip>
    <port>3306</PORT>
  </server>
</servers>

问题分析 :

  1. 第一个 <server> 没有关闭标签 (规则1)
  2. 第二个 <port> 标签为 </PORT>,大小写不匹配(规则2)

应用正确语法后

<?xml version="1.0" encoding="UTF-8"?>
<servers>
  <server id="web01">
    <name>乐途官网站点</name>
    <ip>192.168.1.100</ip>
    <port>8080</port>
  </server>
  <server id="db01">
    <name>主数据库</name>
    <ip>192.168.1.200</ip>
    <port>3306</port>
  </server>
</servers>

操作结果

当小崔改正了两处语法错误后,XML 解析顺利通过。后来他发现线上之所以"正常",是因为运维 大翔 在部署前手动用 xmllint 检查并修复了文件——只是没把修复后的版本同步回开发仓库。这导致了一个典型的"线上正常、本地报错"的配置漂移问题。

小崔总结了两条教训:

  1. XML 的严格语法是好事——如果语法错了但程序"正常"运行,那一定是程序在静默吞掉错误
  2. 配置文件必须纳入版本控制,不能靠人工"修完就用"

易错场景

错误一:在属性值中使用未转义的双引号

<!-- ❌ 属性值中的双引号会提前结束属性 -->
<book title="He said "Hello" to me">

<!-- ✅ 使用单引号包裹,或实体引用 -->
<book title='He said "Hello" to me'>
<book title="He said &quot;Hello&quot; to me">

错误二:注释中包含双连字符

<!-- ❌ 注释中不能包含 -- -->
<!-- 这是一个 -- 不好的注释 -->

<!-- ✅ 避免连续的两个短横线 -->
<!-- 这是一个正确的注释 -->

错误三:CDATA 段中误放 ]]>

<!-- ❌ CDATA 结束符出现在内容中 -->
<script>
<![CDATA[
  if (str.endsWith("]]>")) { }  <!-- 解析器会在这里提前结束 CDATA -->
]]>
</script>

<!-- ✅ 拆分 CDATA 段 -->
<script>
<![CDATA[
  if (str.endsWith("]]") + ">") { }
]]>
</script>

面试考点

考点参考答案要点
为什么 XML 采用 fatal error 而非容错策略?XML 是数据交换格式而非显示格式——错误的数据比没有数据更危险。严格的语法让解析器实现简单(W3C 设计目标第4条),也让数据接收方可以信赖解析结果
什么时候用 CDATA 段,什么时候用实体引用?少量特殊字符用实体引用(&lt;),大段代码/脚本用 CDATA。CDATA 不能嵌套,内容不能含 ]]>
XML 声明 <?xml version="1.0" encoding="UTF-8"?> 是必须的吗?XML 1.0 中可选但强烈推荐;XML 1.1 中必需。encoding 默认 UTF-8。如果文档以 UTF-16 编码且没有声明,解析器可能无法正确识别
上一页
XML 属性
下一页
XML 命名空间