XML Schema 概述
本章定位 :理解 XSD(XML Schema Definition)的设计目的、与 DTD 的全面对比,以及 Schema 文档的根元素结构。XSD 是 DTD 的现代替代品,用 XML 语法写 Schema,支持丰富的数据类型和命名空间。
定义与作用
XSD (XML Schema Definition)是 W3C 于 2001 年发布的 XML 文档结构定义语言。它用 XML 语法本身来定义 XML 文档的合法结构——包括元素、属性、数据类型和出现次数。
XSD 解决 DTD 的四个核心缺陷:
- 数据类型不足 :DTD 只能区分文本/子元素,XSD 有 44+ 内置类型(integer、decimal、date、boolean...)
- 语法不统一 :DTD 不是 XML,需要单独的解析器;XSD 本身就是 XML,可以用 XML 工具链处理
- 命名空间支持弱 :DTD 对命名空间支持有限;XSD 原生支持 targetNamespace 和命名空间限定
- 扩展性差 :DTD 不能定义复杂约束(如正则模式、值的范围);XSD 通过 Facets 提供细粒度约束
核心原理:DTD vs XSD 对比
图解释 :XSD 是"用 XML 写 Schema"——Schema 本身也是 XML 文档,可以被 XPath 查询、被 XSLT 转换、被 DOM 操作。DTD 是非 XML 语法,需要单独的解析器。
语法/结构要点
DTD vs XSD 全面对比
| 维度 | DTD | XSD |
|---|---|---|
| 语法 | 非 XML(单独的语法) | XML 语法 |
| 数据类型 | CDATA(字符串) | 44+ 内置类型 + 自定义类型 |
| 命名空间 | 弱支持 | 原生支持 targetNamespace |
| 扩展性 | 无法自定义约束 | Facets(枚举、正则、范围...) |
| 后缀 | .dtd | .xsd |
| 默认值 | 支持 | 支持 |
| 出现次数 | + / * / ? | minOccurs / maxOccurs |
Schema 根元素结构
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="https://learnto.cn/bookstore"
xmlns="https://learnto.cn/bookstore"
elementFormDefault="qualified">
<!-- 元素和类型声明 -->
</xs:schema>
| 属性 | 含义 |
|---|---|
xmlns:xs | 将 xs: 前缀绑定到 Schema 标准命名空间 |
targetNamespace | 定义当前 Schema 描述的 XML 文档的命名空间 |
elementFormDefault | qualified 时局部元素必须用命名空间前缀 |
完整示例:白歌用 XSD 重写图书 Schema
场景说明
飞翔科技架构师 白歌 之前用 DTD 为图书系统编写了验证规则,但 DTD 无法验证"价格是正数"这种约束。她决定用 XSD 重写,利用 XSD 的数据类型和 Facets 提供更严格的验证。
操作前:DTD 版本(无数据类型检查)
<!ELEMENT bookstore (book+)>
<!ELEMENT book (title, author+, year, price)>
<!ELEMENT title (#PCDATA)>
<!ELEMENT author (#PCDATA)>
<!ELEMENT year (#PCDATA)>
<!ELEMENT price (#PCDATA)>
<!ATTLIST book id ID #REQUIRED category CDATA #REQUIRED>
<!ATTLIST title lang CDATA #IMPLIED>
操作后:XSD 版本(含数据类型 + Facets)
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="https://learnto.cn/bookstore"
xmlns="https://learnto.cn/bookstore"
elementFormDefault="qualified">
<xs:element name="bookstore">
<xs:complexType>
<xs:sequence>
<xs:element name="book" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="title" type="TitleType"/>
<xs:element name="author" type="xs:string" maxOccurs="unbounded"/>
<xs:element name="year" type="xs:gYear"/>
<xs:element name="price">
<xs:simpleType>
<xs:restriction base="xs:decimal">
<xs:minInclusive value="0.01"/>
<xs:fractionDigits value="2"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
</xs:sequence>
<xs:attribute name="id" type="xs:ID" use="required"/>
<xs:attribute name="category" type="xs:string" use="required"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="TitleType">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="lang" type="xs:language" default="en"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:schema>
操作结果
XSD 版本新增的验证能力:
year必须是合法年份(xs:gYear),2005可以通过,abcd不行price必须 ≥ 0.01 且最多 2 位小数author可以多个(maxOccurs="unbounded")lang必须是合法的语言代码(en、zh-CN等),默认enid是必填属性(use="required")
白歌总结:"DTD 检查的是'有没有',XSD 能检查'对不对'。"
易错场景
错误一:混淆 targetNamespace 和 xmlns:xs
<!-- xmlns:xs 是 Schema 标准命名空间(固定的) -->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
<!-- targetNamespace 是你定义的业务命名空间(自定义的) -->
targetNamespace="https://learnto.cn/bookstore">
错误二:elementFormDefault 设置错误
elementFormDefault="unqualified" 时,XSD 定义的局部元素不需要命名空间前缀。这容易让使用者困惑——建议始终设为 qualified。
面试考点
| 考点 | 参考答案要点 |
|---|---|
| XSD 相比 DTD 的三大优势? | ①丰富数据类型(44+内置+自定义);②原生命名空间支持;③细粒度约束(Facets:枚举、正则、范围) |
| XSD 的根元素有哪些关键属性? | xmlns:xs(Schema 标准命名空间)、targetNamespace(目标命名空间)、elementFormDefault(局部元素命名空间限定方式) |
| 什么场景下用 DTD 更合适? | 简单文档验证、遗留系统兼容、对数据类型要求不高的场景。XSD 学习曲线更陡但功能更强 |