xs:key和xs:keyref是在XSD中实现XML实例内引用完整性验证的机制,非数据库主外键;xs:key定义作用域内唯一非空标识,xs:keyref强制字段值匹配某xs:key值,二者均受限于作用域、简单XPath及单文档约束。

xs:key 和 xs:keyref 是 XSD 中用于在 XML 文档内实现“类主键-外键”约束的机制,但要注意:它们**不是数据库意义上的主外键**,而是在 XML 实例验证阶段强制要求的引用完整性检查,不涉及存储或执行逻辑。
xs:key 定义唯一标识(类似主键)
它声明某个元素(或属性)的值在整个文档范围内必须唯一,且非空。常用于标记“可被引用的主标识”。
- 必须放在
<xs:element>或<xs:complexType>内的<xs:unique>、<xs:key>或<xs:keyref>中(推荐用<xs:key>表示主标识) - 作用域是其所在元素及其所有后代(即“当前作用域”),不是整个文档全局——这点容易误解
- 用
<xs:selector>指定候选元素范围,用<xs:field>指定提取哪个字段(支持 XPath 表达式,但仅限一级路径如@id或name)
示例:为每个 <book> 定义唯一 isbn:
<xs:key name="bookKey"> <xs:selector xpath="book"/> <xs:field xpath="@isbn"/> </xs:key>
xs:keyref 建立引用关系(类似外键)
它声明某元素/属性的值,必须匹配某个 xs:key(或 xs:unique)定义的值,从而形成引用约束。
-
refer属性必须指向一个已定义的xs:key或xs:unique的name - 它的
<xs:selector>范围和<xs:field>路径,要能提取出待校验的“外键值” - 被引用的
xs:key必须在同一作用域或更外层作用域中定义(不能在子作用域里定义 key 再在外层 keyref 引用)
示例:让 <order> 中的 bookIsbn 引用上面定义的 bookKey:
<xs:keyref name="orderBookRef" refer="bookKey"> <xs:selector xpath="order"/> <xs:field xpath="@bookIsbn"/> </xs:keyref>
关键限制与常见陷阱
- 不支持跨文档引用:所有 key/keyref 必须在同一 XSD 文件中定义,且目标元素必须在同一个 XML 实例中存在
- XPath 表达式能力有限:只支持
@attr、element、element/@attr这类简单路径,不支持函数(如string())、轴(如../)或谓词复杂条件 - 作用域易错:key/keyref 只对
<xs:selector>选中的元素及其后代生效;若把 key 定义在局部 complexType 里,那它只管该类型实例内部,无法被父级 keyref 引用 - 空值不通过:key 字段值为空(包括空白字符串)会导致验证失败,所以确保被 key 约束的属性/元素有值










