XSD 简单类型
本章定位 :掌握 XSD 简单类型(simpleType)的定义方式——内置类型(string/decimal/integer/date/boolean)、restriction 约束面(Facets)和自定义类型的创建。
定义与作用
在 XSD 中, 简单类型 (simpleType)指不能包含子元素且不能有属性的类型——只包含文本内容,但可以对该文本施加精确约束。
简单类型是 XSD 相比 DTD 的最大进步之一。DTD 只能声明"这里是文本",XSD 可以声明"这里是一个 0 到 100 的整数,且必须是 5 的倍数"。这种精确约束使得数据验证从"有没有字段"升级为"字段值是否正确"。
核心原理:类型层次与 Facets 约束
图解释 :XSD 类型系统以 anyType 为根。简单类型分为内置的和自定义的。自定义简单类型通过对基类型施加 Facets 约束面来精确定义允许的取值范围。
语法/结构要点
常用内置简单类型
| 类型 | 示例值 | 说明 |
|---|---|---|
xs:string | "Hello World" | 字符串,最常用 |
xs:decimal | 39.95 | 高精度十进制数 |
xs:integer | 42 | 整数 |
xs:int | -2147483648 | 32位有符号整数 |
xs:boolean | true / false / 1 / 0 | 布尔值 |
xs:date | 2024-01-15 | 日期 |
xs:time | 14:30:00 | 时间 |
xs:dateTime | 2024-01-15T14:30:00 | 日期时间 |
xs:gYear | 2003 | 年份 |
约束面(Facets)
| Facet | 作用 | 示例 |
|---|---|---|
enumeration | 限制为给定值集合 | <xs:enumeration value="web"/> |
pattern | 正则表达式匹配 | <xs:pattern value="[A-Z]{3}-\\d{4}"/> |
minLength / maxLength | 字符串长度范围 | <xs:minLength value="1"/> |
minInclusive / maxInclusive | 数值范围(含边界) | <xs:minInclusive value="0.01"/> |
minExclusive / maxExclusive | 数值范围(不含边界) | <xs:maxExclusive value="100"/> |
fractionDigits | 小数最大位数 | <xs:fractionDigits value="2"/> |
totalDigits | 总位数 | <xs:totalDigits value="8"/> |
完整示例:黄俪为选课系统添加数据验证
场景说明
飞翔科技的测试工程师 黄俪 发现选课系统的 XML 中有各种脏数据:学号格式不统一、分数超出范围、邮箱格式错误。她决定用 XSD 简单类型的 Facets 来消除这些问题。
操作前:无约束的数据
<?xml version="1.0" encoding="UTF-8"?>
<enrollments>
<student id="abc" name="小崔" grade="A+" score="105" email="bad-email"/>
<student id="2024002" name="" grade="X" score="-5" email="good@learnto.cn"/>
</enrollments>
操作后:XSD 自定义简单类型约束
enrollment.xsd :
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- 学号:7位数字 -->
<xs:simpleType name="StudentIdType">
<xs:restriction base="xs:string">
<xs:pattern value="\d{7}"/>
</xs:restriction>
</xs:simpleType>
<!-- 姓名:非空,最多30个字符 -->
<xs:simpleType name="NameType">
<xs:restriction base="xs:string">
<xs:minLength value="1"/>
<xs:maxLength value="30"/>
</xs:restriction>
</xs:simpleType>
<!-- 成绩等级:限定枚举 -->
<xs:simpleType name="GradeType">
<xs:restriction base="xs:string">
<xs:enumeration value="A+"/>
<xs:enumeration value="A"/>
<xs:enumeration value="B+"/>
<xs:enumeration value="B"/>
<xs:enumeration value="C"/>
<xs:enumeration value="F"/>
</xs:restriction>
</xs:simpleType>
<!-- 分数:0~100,整数 -->
<xs:simpleType name="ScoreType">
<xs:restriction base="xs:integer">
<xs:minInclusive value="0"/>
<xs:maxInclusive value="100"/>
</xs:restriction>
</xs:simpleType>
<!-- 邮箱:正则 -->
<xs:simpleType name="EmailType">
<xs:restriction base="xs:string">
<xs:pattern value="[^@]+@[^@]+\.[^@]+"/>
</xs:restriction>
</xs:simpleType>
<xs:element name="enrollments">
<xs:complexType>
<xs:sequence>
<xs:element name="student" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute name="id" type="StudentIdType" use="required"/>
<xs:attribute name="name" type="NameType" use="required"/>
<xs:attribute name="grade" type="GradeType"/>
<xs:attribute name="score" type="ScoreType"/>
<xs:attribute name="email" type="EmailType"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
操作结果
XSD 验证后,操作前的脏数据全部被拦截:
id="abc"→ 不符合正则\d{7}grade="A+"→ 实际上可以通过(在枚举列表中)score="105"→ 超出 0~100 范围 ❌email="bad-email"→ 不符合邮箱正则 ❌name=""→ minLength=1,空字符串不通过 ❌grade="X"→ 不在枚举列表中 ❌
易错场景
错误一:pattern 正则忘加锚点
<!-- ❌ 匹配任何包含数字的字符串("abc123def"也通过) -->
<xs:pattern value="\d{7}"/>
<!-- ✅ XSD pattern 默认完全匹配,\d{7} 等同于 ^\d{7}$ -->
<xs:pattern value="\d{7}"/>
XSD 的 pattern Facet 默认对整个值进行完全匹配,不需要 ^ 和 $。
错误二:integer vs int 混淆
xs:integer:任意大小的整数xs:int:32 位有符号整数(-2147483648 ~ 2147483647)
如果学号可能超过 21 亿,用 xs:int 会溢出——应该用 xs:integer。
面试考点
| 考点 | 参考答案要点 |
|---|---|
| XSD 简单类型和复杂类型的区别? | 简单类型只含文本不含子元素/属性;复杂类型可含子元素和/或属性。简单类型可通过 Facets 对值施加约束 |
| 列出 5 个常用的 XSD 约束面 | enumeration(枚举)、pattern(正则)、minLength/maxLength(长度)、minInclusive/maxInclusive(数值范围)、fractionDigits(小数位数) |
| XSD 中如何限制整数范围 1~100? | 定义 simpleType,restriction base="xs:integer",设 minInclusive="1" maxInclusive="100" |