XML无法通过定义key/keyref的XSD验证,求技术支持
解决XSD中Keyref无法找到引用Key的问题
问题背景
使用Visual Studio 2022编辑并测试XML与XSD文件,需要实现Workload中的Package必须属于已定义的可用Package的验证逻辑。XSD本身可正常验证,但验证XML时,WorkloadPackage元素的Keyref约束报错,提示无法找到作用域内引用的key或unique,问题出在key和keyref的作用域及XPath选择器定义上。
报错信息
Warning The Keyref 'http://widgetcorp.com/test.xsd:WorkloadPackage' cannot find the referred key or unique in scope. config E:\kode\test.xml 7
问题分析
原XSD存在两个核心问题:
- 作用域不匹配:
PackageKey定义在Package元素内部,作用域仅局限于单个Package节点;packageRef定义在WorkloadPackage元素内部,作用域仅局限于单个WorkloadPackage节点。两者不在同一作用域,导致keyref无法找到对应的key。 - 约束定义位置错误:key/keyref是针对整个文档的全局约束,应定义在根元素
UbergenPackages下,而非子元素内部。
修正后的XSD代码
将xs:key和xs:keyref移动到根元素UbergenPackages的定义下,使其作用域覆盖整个文档,同时删除原元素内部的key/keyref定义:
<?xml version="1.0" encoding="utf-8"?> <xs:schema targetNamespace="http://widgetcorp.com/test.xsd" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:ugpk="http://widgetcorp.com/test.xsd" elementFormDefault="qualified" > <xs:element name="UbergenPackages"> <xs:complexType> <xs:sequence> <xs:element ref="ugpk:Workloads" /> <xs:element ref="ugpk:Packages" /> </xs:sequence> </xs:complexType> <!-- 定义Package的唯一键,作用域覆盖整个UbergenPackages --> <xs:key name="PackageKey"> <xs:selector xpath="ugpk:Packages/ugpk:Package"/> <xs:field xpath="@name"/> </xs:key> <!-- 定义WorkloadPackage对PackageKey的引用,作用域覆盖整个UbergenPackages --> <xs:keyref name="packageRef" refer="ugpk:PackageKey"> <xs:selector xpath="ugpk:Workloads/ugpk:Workload/ugpk:WorkloadPackage"/> <xs:field xpath="@name"/> </xs:keyref> </xs:element> <xs:element name="Workloads"> <xs:annotation> <xs:documentation> Workloads </xs:documentation> </xs:annotation> <xs:complexType> <xs:sequence> <xs:element ref="ugpk:Workload" minOccurs="1" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="Workload"> <xs:annotation> <xs:documentation> Workload </xs:documentation> </xs:annotation> <xs:complexType> <xs:sequence> <xs:element ref="ugpk:WorkloadPackage" minOccurs="1" maxOccurs="unbounded" /> </xs:sequence> <xs:attribute name="name" type="xs:string"/> </xs:complexType> </xs:element> <xs:element name="WorkloadPackage"> <xs:annotation> <xs:documentation> Workload Package </xs:documentation> </xs:annotation> <xs:complexType> <xs:attribute name="name" type="xs:IDREF" use="required"/> <xs:attribute name="desc" type="xs:string" use="optional" /> <xs:attribute name="loader" type="xs:string" use="optional" /> <xs:attribute name="variable" type="xs:string" use="optional" /> </xs:complexType> </xs:element> <xs:element name="Packages"> <xs:annotation> <xs:documentation> Packages </xs:documentation> </xs:annotation> <xs:complexType> <xs:sequence> <xs:element ref="ugpk:Package" minOccurs="1" maxOccurs="unbounded"></xs:element> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="Package"> <xs:annotation> <xs:documentation> Package Details. With mapping to OS and release/version. </xs:documentation> </xs:annotation> <xs:complexType> <xs:sequence> <xs:element name="Module" minOccurs="1" maxOccurs="unbounded"> <xs:complexType> <xs:attribute name="osname" type="xs:string" use="required"/> <xs:attribute name="packageid" type="xs:string" use="required"/> </xs:complexType> </xs:element> </xs:sequence> <xs:attribute name="name" type="xs:ID" use="required"/> </xs:complexType> </xs:element> <!-- Package Name --> <xs:simpleType name="PackageName"> <xs:annotation> <xs:documentation> Package Name </xs:documentation> </xs:annotation> <xs:restriction base="xs:string"> <xs:pattern value="([A-Za-z0-9][-_A-Za-z0-9]+)"/> </xs:restriction> </xs:simpleType> </xs:schema>
验证效果
修改后,使用Visual Studio 2022验证原XML文件可正常通过:
- 当
WorkloadPackage的name属性值存在于Packages下的Package的name中时,验证通过; - 若
WorkloadPackage引用了未定义的Package名称,会触发验证错误,符合需求。
内容的提问来源于stack exchange,提问作者mipatriot
相关产品推荐
相关产品推荐

