XSD unique约束配置问题:跨book重复author-ref触发验证错误
问题根源与解决方案
咱们直接戳破问题:你遇到的错误,根源是唯一约束的作用范围搞错了——你定义的authorIdUniqueConstraint把整个<library>下的所有author-ref都纳入了全局唯一性校验,完全违反了你“不同book可以包含相同author-ref”的需求。
为什么原写法会出错?
你把<xs:unique>直接放在根元素<library>下面,它的<xs:selector xpath="./book/author-ref"会选中library下每一本book里的每一个author-ref节点,然后强制要求所有这些节点的内容全局唯一。所以当第二本书里出现T.Pratchett时,就和第一本书里的重复了,触发了唯一性校验错误。
正确实现:把约束限定在单本书内
要实现“单本书内author-ref唯一,跨书可以重复”,必须把<xs:unique>约束放到<book>元素的定义里,让它的作用范围缩小到单个book节点内部。
修正后的XSD(复用bookType的简洁写法)
<?xml version="1.0" encoding="ISO-8859-1"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> <!-- 简单类型定义 --> <xs:simpleType name="yearType"> <xs:restriction base="xs:int"> <xs:pattern value="[0-9][0-9][0-9][0-9]"/> </xs:restriction> </xs:simpleType> <!-- 复杂类型定义 --> <xs:complexType name="authorType"> <xs:sequence> <xs:element name="last-name" type="xs:string"/> <xs:element name="first-name" type="xs:string"/> </xs:sequence> <xs:attribute name="id" use="required" type="xs:string"/> </xs:complexType> <xs:complexType name="bookType"> <xs:sequence> <xs:element name="author-ref" minOccurs="1" maxOccurs="10" type="xs:string"/> <xs:element name="title" type="xs:string"/> <xs:element name="language" type="xs:language" minOccurs="0"/> <xs:element name="year" type="yearType" minOccurs="0"/> </xs:sequence> </xs:complexType> <!-- 根元素library定义 --> <xs:element name="library"> <xs:complexType> <xs:sequence> <!-- 在这里给book元素添加内部唯一约束 --> <xs:element name="book" type="bookType" maxOccurs="unbounded"> <xs:unique name="bookAuthorRefUnique"> <!-- 选择当前book下的所有author-ref --> <xs:selector xpath="./author-ref"/> <!-- 约束的是author-ref的文本内容 --> <xs:field xpath="."/> </xs:unique> </xs:element> <xs:element name="author" type="authorType" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <!-- 保留原有的key和keyref,保证author-ref对应存在的author id --> <xs:key name="authorId"> <xs:selector xpath="./author"/> <xs:field xpath="@id"/> </xs:key> <xs:keyref name="authorIdRef" refer="authorId"> <xs:selector xpath="./book/author-ref"/> <xs:field xpath="."/> </xs:keyref> </xs:element> </xs:schema>
逻辑说明
当<xs:unique>定义在<book>元素内部时,它的选择器是以当前book为上下文的:./author-ref只会选中当前这本书里的所有author-ref节点,然后强制要求这些节点在本书范围内唯一。这样:
- 同一本书里不能重复引用同一个作者(满足你的条件1)
- 不同书之间完全可以引用同一个作者(满足你的条件2)
你原来的key和keyref逻辑是对的——它保证了所有author-ref的值都能在<author>节点的id属性中找到,这个校验逻辑可以完整保留。
内容的提问来源于stack exchange,提问作者flyingaxel
相关产品推荐
相关产品推荐

