XSD中的key和keyref怎么用 定义XML唯一性和引用约束

xs:key和xs:keyref用于建立XSD中主键–外键式强一致性约束:key定义必存在、非空、全局唯一的标识,keyref校验引用值是否在key/unique的合法值集合中;二者须配合使用且作用域需重叠或嵌套。

在XSD中,xs:keyxs:keyref是用来建立强一致性约束的核心机制,本质是模拟数据库的“主键–外键”关系。它们必须配合使用,不能单独存在;key定义谁是“被引用的唯一标识”,keyref定义谁“引用了它”,且二者作用域需重叠或嵌套。

key:定义强制存在的唯一标识

xs:key要求指定字段**必须存在、非空、全局唯一**(在它的作用域内)。它由三部分组成:

  • name:约束名称,用于keyrefrefer属性引用
  • xs:selector:XPath表达式,选中要检查的一组元素(如xpath="book"
  • xs:field:XPath表达式,指出每个被选元素中哪个值参与唯一性校验(如xpath="@isbn"xpath="title"

例如,确保每本bookisbn属性不为空且全文档唯一:


  
  

keyref:定义对key的引用关系

xs:keyref本身不保证唯一性,只校验“所填的值是否在某个keyunique定义的合法值集合中”。它也必须包含namexs:selectorxs:field,外加一个关键属性:

  • refer:必须指向一个已定义的xs:keyxs:uniquename

例如,定义order中的book_isbn必须引用已有bookisbn


  
  

注意:order/book_isbn文本内容必须等于某本book/@isbn的值,否则XML验证失败。

key vs unique:什么时候用哪个?

二者结构相同,但语义不同:

  • xs:key:字段值必须存在且非空,适合做主键(如ID、ISBN)
  • xs:unique:字段值可为空或缺失,缺失时跳过校验,适合宽松唯一场景(如可选的邮箱、备用编号)
  • xs:keyref只能引用xs:keyxs:unique,不能引用另一个keyref

若你允许某字段为空但一旦有值就必须唯一,用unique;若该字段是核心标识、绝不允许缺省,就用key

常见陷阱与建议

实际编写时容易出错的地方:

  • xs:selector的XPath必须匹配到元素,不能写错层级(比如xpath="books/book" vs xpath="book"
  • xs:field路径必须返回单个原子值;写成xpath="author/name"可能返回多个节点,导致验证异常
  • keykeyref必须定义在同一个xs:elementxs:schema范围内,跨复杂类型需注意作用域嵌套
  • 若XML实例中key对应元素根本不存在,整个key约束失效(不会报错),所以确保数据结构覆盖完整