XSD 复杂类型
本章定位 :掌握 XSD 复杂类型(complexType)的定义方式——三种指示器(sequence/choice/all)、出现次数控制(minOccurs/maxOccurs)、属性声明和混合内容。
定义与作用
复杂类型 (complexType)是可以包含子元素和/或属性的类型。在 XSD 中,任何有结构的元素都需要用 complexType 定义——包括包含子元素的复合元素和带属性的纯文本元素。
复杂类型的核心能力:
- 定义子元素的顺序和出现次数(通过指示器和 minOccurs/maxOccurs)
- 声明元素可以携带的属性
- 支持混合内容(同时包含文本和子元素)
核心原理:三种指示器决定子元素结构
图解释 :三种指示器控制子元素的组织方式。sequence 最常用(有序必含),choice 用于"二选一"场景,all 适合"全部含但顺序随意"的简单表单。
语法/结构要点
三种指示器
| 指示器 | 子元素顺序 | 出现次数限制 | 典型场景 |
|---|---|---|---|
sequence | 严格按声明顺序 | 任意(minOccurs/maxOccurs) | person(name, age, address) |
choice | 只选一个 | 任意 | 联系方式(phone |
all | 任意顺序 | 每个最多 1 次 | 简单表单(name, email, phone) |
出现次数控制
| 属性 | 含义 | 常用值 |
|---|---|---|
minOccurs | 最少出现次数 | 0(可选)、1(必含,默认) |
maxOccurs | 最多出现次数 | 1(默认)、unbounded(无限制) |
属性声明
<xs:attribute name="id" type="xs:ID" use="required"/>
<xs:attribute name="category" type="xs:string" use="optional" default="misc"/>
| use 值 | 含义 |
|---|---|
required | 必须提供 |
optional | 可选(默认) |
prohibited | 禁止使用 |
完整示例:小崔设计订单系统 XSD
场景说明
飞翔科技的后端开发 小崔 被派去设计订单系统的 XML Schema。订单结构比较复杂:有些字段必填,有些二选一(快递地址 vs 自提点),商品数量可变。
操作前:粗糙的 DTD 声明
<!ELEMENT order (items, shipping, billing)>
<!ELEMENT items (item+)>
<!ELEMENT item (name, quantity, price)>
<!-- 无法表达 shipping 和 billing 的复杂结构 -->
操作后:XSD complexType 设计
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="order">
<xs:complexType>
<xs:sequence>
<!-- 商品列表:至少1个 -->
<xs:element name="items">
<xs:complexType>
<xs:sequence>
<xs:element name="item" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="name" type="xs:string"/>
<xs:element name="quantity">
<xs:simpleType>
<xs:restriction base="xs:integer">
<xs:minInclusive value="1"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="price" type="xs:decimal"/>
</xs:sequence>
<xs:attribute name="sku" type="xs:string" use="required"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<!-- 收货方式:快递 or 自提(二选一) -->
<xs:element name="delivery">
<xs:complexType>
<xs:choice>
<xs:element name="express">
<xs:complexType>
<xs:all>
<xs:element name="address" type="xs:string"/>
<xs:element name="city" type="xs:string"/>
<xs:element name="zip" type="xs:string"/>
<xs:element name="phone" type="xs:string" minOccurs="0"/>
</xs:all>
</xs:complexType>
</xs:element>
<xs:element name="pickup">
<xs:complexType>
<xs:sequence>
<xs:element name="store_name" type="xs:string"/>
<xs:element name="pickup_time" type="xs:dateTime"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="id" type="xs:string" use="required"/>
<xs:attribute name="status" type="xs:string" default="pending"/>
</xs:complexType>
</xs:element>
</xs:schema>
操作结果
符合 Schema 的订单 XML:
<order id="ORD-2024-001" status="pending">
<items>
<item sku="XML-101">
<name>Learning XML</name>
<quantity>2</quantity>
<price>39.95</price>
</item>
</items>
<delivery>
<express>
<address>天河路100号飞翔科技大厦</address>
<city>广州</city>
<zip>510630</zip>
</express>
</delivery>
</order>
XSD 确保:①quantity ≥ 1;②收货方式只能是 express 或 pickup 二选一;③express 中 address/city/zip 必填但顺序随意;④status 不填则默认 pending。
易错场景
错误一:混淆 all 和 sequence
<!-- all:子元素顺序任意,每个最多1次 -->
<xs:all>
<xs:element name="a"/>
<xs:element name="b"/>
</xs:all>
<!-- sequence:必须按声明顺序出现,可以有多个 -->
<xs:sequence>
<xs:element name="a" maxOccurs="unbounded"/>
<xs:element name="b" maxOccurs="unbounded"/>
</xs:sequence>
错误二:maxOccurs 默认值是 1,不是 unbound
<!-- ❌ 若不给 maxOccurs,默认只能出现1次 -->
<xs:element name="item"/>
<!-- ✅ 允许多个 -->
<xs:element name="item" maxOccurs="unbounded"/>
面试考点
| 考点 | 参考答案要点 |
|---|---|
| sequence、choice、all 的区别? | sequence:按序全部;choice:N选一;all:全部但顺序任意,每项最多1次。all 不能嵌套在 sequence 内部 |
| minOccurs 和 maxOccurs 的默认值? | 默认都是 1。maxOccurs="unbounded" 表示无上限。minOccurs="0" 使元素可选 |
| complexType 如何声明属性? | 在 complexType 内部的最后使用 <xs:attribute> 声明,`use="required |