xs:key定义主键时,selector必须匹配元素且field指向直接子元素或属性;key与keyref须同作用域、refer严格匹配name;校验需显式启用并注意空格和命名空间。

xs:key 定义主键时,必须确保 selector 匹配到元素,且 field 指向实际存在的子元素或属性
很多人写 xs:key 时 XML 校验不报错但约束无效,根本原因是 selector 路径没匹配到任何元素,或者 field 写成了不存在的子节点名。XSD 不会主动告诉你“没找到字段”,它只是默默跳过约束。
-
selector必须是相对路径,从被声明的元素开始算起;比如在<books>下定义 key,selector="book"才能选中每个<book> -
field值必须是selector匹配元素的**直接子元素或属性**;写field="@isbn"没问题,但写field="meta/isbn"就无效(XPath 1.0 不支持嵌套路径) - 多个
field可以联合唯一,但所有field必须在同一层级上存在;不能一个取属性、一个取深层子元素
xs:keyref 引用 xs:key 时,refer 属性值必须和 key 的 name 完全一致,且作用域需重叠
xs:keyref 不是靠名字“猜”哪个 key,而是严格按 refer 属性字面量绑定。常见错误是大小写拼错、多空格、或把 key 定义在了外层 complexType 里,而 keyref 在内层 element 中引用——这时作用域不覆盖,校验器直接忽略该 keyref。
-
refer的值必须是 schema 中已声明的xs:key的name,比如<xs:key name="book-id-key">,那么 keyref 的refer就得是"book-id-key",少一个横线都不行 - key 和 keyref 必须在同一个 scope:要么都在根
<xs:schema>下,要么都在同一个<xs:element>或<xs:complexType>内部;跨 scope 引用无效 - keyref 的
selector匹配的元素,其field值必须能在对应 key 的所有匹配元素中找到;否则报cvc-identity-constraint.4.2错误
用 xs:key / keyref 校验时,XML 解析器行为差异大,别依赖默认设置
不是所有 XML 工具都默认开启 identity constraint 校验。Java 的 DocumentBuilder 默认关,Python 的 lxml 需显式传 schema 对象,而某些编辑器(如 VS Code 的 XML 插件)只做基础语法检查,完全不跑 key/keyref。
- Java JAXB:
SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI)创建后,必须用newSchema.newValidator()显式校验,否则 key 约束不生效 - Python lxml:
XMLSchema实例必须调用.validate(doc),且doc是etree.XML解析后的对象,不是字符串 - 命令行 xerces 或 xmllint:需加
-schema参数,且 XSD 文件路径不能含中文或空格(某些版本会静默失败)
主键值为空或重复时,错误信息模糊,调试要从验证入口开始查
典型报错像 cvc-identity-constraint.4.3 或 cvc-identity-constraint.4.1,但不告诉你具体哪一行、哪个字段出问题。这是因为 key/keyref 是全局扫描式校验,错误定位天然滞后。
- 先确认 key 的
selector是否真匹配到了元素(可在 XSD 中临时加个<xs:assert test="count(book) > 0"/>辅助判断) - 把 XML 中疑似有问题的块单独拎出来,配合最小化 XSD 测试,排除命名空间干扰(
xs:key对 namespace 敏感) - 注意 whitespace:如果
field指向文本节点(如field="isbn"),而 XML 里<isbn> 978-0-306-40615-7 </isbn>有前后空格,会导致去重失败——XSD 默认不 trim










