XSD 命名空间与引用
本章定位 :掌握 XSD 中 targetNamespace 的作用、elementFormDefault 的影响,以及 xs:include(同命名空间复用)和 xs:import(跨命名空间引用)的区别。
定义与作用
当 Schema 变得复杂时,需要模块化拆分。XSD 提供两种复用机制:
- xs:include :引入同一命名空间的另一个 Schema 文件(像 C 的
#include) - xs:import :引用不同命名空间的 Schema 组件(像 Java 的
import)
targetNamespace 定义了当前 Schema 描述的 XML 文档的命名空间。elementFormDefault 控制局部元素是否需要命名空间前缀——这直接影响生成的 XML 的冗长程度。
核心原理:include vs import
图解释 :xs:include 用于同一命名空间的模块拆分(如 book.xsd 和 author.xsd 同属 bookstore 命名空间);xs:import 用于跨命名空间引用(如 order.xsd 引用 common.xsd 中定义的地址类型)。
语法/结构要点
include vs import
| 特性 | xs:include | xs:import |
|---|---|---|
| 用途 | 引入同命名空间的 Schema | 引用不同命名空间的 Schema |
| schemaLocation | 本地文件路径 | 本地文件路径 |
| namespace | 无须指定(自动继承) | 必须指定引用的命名空间 |
| 效果 | 如同合并为一个 Schema | 引用另一命名空间的类型/元素 |
elementFormDefault
| 值 | 效果 | XML 示例 |
|---|---|---|
qualified | 局部元素必须有命名空间前缀 | <ns:book xmlns:ns="..."><ns:title/></ns:book> |
unqualified | 局部元素不需要前缀 | <ns:book xmlns:ns="..."><title/></ns:book> |
完整示例:白歌模块化飞翔科技 XSD
场景说明
飞翔科技的架构师 白歌 发现图书系统的 XSD 文件已经 300 行了。她决定将 Schema 拆分为通用类型(common.xsd)和图书专用(bookstore.xsd),使用 include 和 import 组合。
common.xsd(通用类型库)
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="https://learnto.cn/common"
xmlns="https://learnto.cn/common"
elementFormDefault="qualified">
<!-- 金额类型:正数,2位小数 -->
<xs:simpleType name="MoneyType">
<xs:restriction base="xs:decimal">
<xs:minInclusive value="0.01"/>
<xs:fractionDigits value="2"/>
</xs:restriction>
</xs:simpleType>
<!-- 地址复杂类型 -->
<xs:complexType name="AddressType">
<xs:sequence>
<xs:element name="street" type="xs:string"/>
<xs:element name="city" type="xs:string"/>
<xs:element name="zip" type="xs:string"/>
<xs:element name="country" type="xs:string" default="中国"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
bookstore.xsd(图书专用 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"
xmlns:cmn="https://learnto.cn/common"
elementFormDefault="qualified">
<!-- 引入同命名空间的 author.xsd -->
<xs:include schemaLocation="author.xsd"/>
<!-- 导入不同命名空间的 common.xsd -->
<xs:import namespace="https://learnto.cn/common"
schemaLocation="common.xsd"/>
<xs:element name="bookstore">
<xs:complexType>
<xs:sequence>
<xs:element name="book" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="title" type="xs:string"/>
<!-- 使用 include 引入的同命名空间类型 -->
<xs:element name="author" type="AuthorType" maxOccurs="unbounded"/>
<!-- 使用 import 引入的跨命名空间类型(需要前缀) -->
<xs:element name="price" type="cmn:MoneyType"/>
<xs:element name="publisher_address" type="cmn:AddressType"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
操作结果
最终 Schema 结构清晰:
- 通用类型(
MoneyType、AddressType)跨多个系统复用 - 图书专用的
AuthorType放在单独文件中,通过include合并 - 跨命名空间引用使用
import+ 前缀
易错场景
错误一:应该用 include 却用了 import
<!-- ❌ author.xsd 和 bookstore.xsd 同一命名空间,应用 include -->
<xs:import namespace="https://learnto.cn/bookstore"
schemaLocation="author.xsd"/>
<!-- ✅ -->
<xs:include schemaLocation="author.xsd"/>
错误二:import 不指定 namespace
xs:import 必须指定 namespace 属性,xs:include 不需要(自动继承父 Schema 的 targetNamespace)。
面试考点
| 考点 | 参考答案要点 |
|---|---|
| xs:include 和 xs:import 的区别? | include:同命名空间合并(无需指定 namespace);import:跨命名空间引用(必须指定 namespace)。如同 C 的 #include vs Java 的 import |
| elementFormDefault 的作用? | qualified 时局部元素必须有命名空间前缀;unqualified 时不需要。qualified 更严格更推荐 |
| 如何实现 XSD 类型跨系统复用? | 将通用类型定义在 common.xsd 中,设独立的 targetNamespace,其他 Schema 通过 xs:import 引用 |