XML与XML Schema基数问题:keyref与key基数不匹配错误解决求助
问题描述
我有一个包含嵌套Filter的XML文件及对应XML Schema,尝试用key和keyref做约束时,出现错误提示:
The cardinality of the fields in keyref 'FilterKeyRef' must be equal to the cardinality of the identity constraint definition 'FilterIdKey'. The cardinality must be '1'
试过在线工具、AI工具及咨询同事仍未解决,求解决方案。
XML示例内容
<?xml version="1.0" encoding="UTF-8"?> <Filters xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="example.xsd"> <Filter> <Id>0</Id> <DisplayName>Filter1</DisplayName> </Filter> <Filter> <Id>1</Id> <DisplayName>Filter2</DisplayName> </Filter> <Filter> <Id>2</Id> <DisplayName>Filter3</DisplayName> <FiltersToInclude> <FilterToInclude> <Id>0</Id> <DisplayName>Filter1</DisplayName> </FilterToInclude> <FilterToInclude> <Id>1</Id> <DisplayName>Filter2</DisplayName> </FilterToInclude> </FiltersToInclude> </Filter> </Filters>
原XML Schema内容
<?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:element name="DisplayName" type="xs:string"/> <xs:element name="Id" type="xs:nonNegativeInteger"/> <xs:element name="Filter"> <xs:complexType> <xs:sequence> <xs:element ref="Id" minOccurs="1" maxOccurs="1"/> <xs:element ref="DisplayName" minOccurs="1" maxOccurs="1"/> <xs:element ref="FiltersToInclude" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="FilterToInclude"> <xs:complexType> <xs:sequence> <xs:element ref="Id" minOccurs="1" maxOccurs="1"/> <xs:element ref="DisplayName" minOccurs="1" maxOccurs="1"/> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="FiltersToInclude"> <xs:complexType> <xs:sequence> <xs:element ref="FilterToInclude" minOccurs="1" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="Filters"> <xs:complexType> <xs:sequence> <xs:element ref="Filter" minOccurs="1" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:key name="FilterIdKey"> <xs:selector xpath="Filter/Id"></xs:selector> <xs:field xpath="."></xs:field> </xs:key> <xs:key name="FilterDisplayNameKey"> <xs:selector xpath="Filter/DisplayName"></xs:selector> <xs:field xpath="."></xs:field> </xs:key> <xs:keyref name="FilterKeyRef" refer="FilterIdKey"> <xs:selector xpath="Filter/FiltersToInclude/FilterToInclude"></xs:selector> <xs:field xpath="./Id"></xs:field> <xs:field xpath="./DisplayName"></xs:field> </xs:keyref> </xs:element> </xs:schema>
问题原因与解决方法
错误原因
- 字段数量不匹配:
FilterIdKey仅定义了1个字段(Id),但FilterKeyRef却定义了2个字段(Id+DisplayName)。XML Schema要求keyref的字段数量必须与所引用的key完全一致,这是报错的核心原因。 - Selector语义错误:原
FilterIdKey的selector选择了Filter/Id节点,这会把每个Id元素当作独立的约束目标,正确逻辑应该是约束每个Filter节点的Id唯一,因此selector应指向Filter节点本身。
修正后的XML Schema
<?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:element name="DisplayName" type="xs:string"/> <xs:element name="Id" type="xs:nonNegativeInteger"/> <xs:element name="Filter"> <xs:complexType> <xs:sequence> <xs:element ref="Id" minOccurs="1" maxOccurs="1"/> <xs:element ref="DisplayName" minOccurs="1" maxOccurs="1"/> <xs:element ref="FiltersToInclude" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="FilterToInclude"> <xs:complexType> <xs:sequence> <xs:element ref="Id" minOccurs="1" maxOccurs="1"/> <xs:element ref="DisplayName" minOccurs="1" maxOccurs="1"/> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="FiltersToInclude"> <xs:complexType> <xs:sequence> <xs:element ref="FilterToInclude" minOccurs="1" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="Filters"> <xs:complexType> <xs:sequence> <xs:element ref="Filter" minOccurs="1" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <!-- 修正key的selector,指向Filter节点,字段为其下的Id --> <xs:key name="FilterIdKey"> <xs:selector xpath="Filter"/> <xs:field xpath="Id"/> </xs:key> <!-- 修正DisplayName唯一约束的selector --> <xs:key name="FilterDisplayNameKey"> <xs:selector xpath="Filter"/> <xs:field xpath="DisplayName"/> </xs:key> <!-- keyref仅保留Id字段,与FilterIdKey字段数量匹配 --> <xs:keyref name="FilterKeyRef" refer="FilterIdKey"> <xs:selector xpath="Filter/FiltersToInclude/FilterToInclude"/> <xs:field xpath="Id"/> </xs:keyref> <!-- 可选:新增DisplayName的引用约束,对应FilterDisplayNameKey --> <xs:keyref name="FilterDisplayNameRef" refer="FilterDisplayNameKey"> <xs:selector xpath="Filter/FiltersToInclude/FilterToInclude"/> <xs:field xpath="DisplayName"/> </xs:keyref> </xs:element> </xs:schema>
关键说明
- 字段数量严格匹配:如果需要同时约束
Id和DisplayName的引用关系,不能在同一个keyref中添加多个字段,必须分别创建两个keyref,各自对应对应的key。 - Selector逻辑清晰:key的selector应选择包含唯一标识的父节点(如
Filter),而非标识节点本身,这样约束的是每个父节点的标识唯一性,符合业务语义。 - 验证效果:修正后的Schema会确保:
- 所有
Filter的Id全局唯一 - 所有
Filter的DisplayName全局唯一(可选) FilterToInclude中的Id必须存在于某个Filter的Id中FilterToInclude中的DisplayName必须存在于某个Filter的DisplayName中(可选)
- 所有
内容的提问来源于stack exchange,提问作者Tobs
相关产品推荐
相关产品推荐

