complexContent限制校验异常:是XSD 1.0规范限制还是Xerces实现问题?
问题1:XSD 1.0下的报错是规范限制还是实现问题?
这是XSD 1.0的固有规范限制,并非Xerces-J的实现bug。
XSD 1.0的粒子限制校验规则中,当派生类型的<sequence>容器仅包含1个子粒子时,校验逻辑会将该外层<sequence>判定为无意义的冗余容器并直接展开,直接拿内层的stuffGroup粒子与基类型t1的外层<sequence>粒子比对。基类型的外层<sequence>未声明出现范围,默认minOccurs=1、maxOccurs=1,和stuffGroup的0~unbounded范围不匹配,因此触发报错。
XSD 1.1更新了派生规则,优化了单粒子容器的处理逻辑,不会再做这种强制展开,因此可以校验通过。所有合规的XSD 1.0实现都会拒绝该Schema,不存在兼容该写法的1.0版本工具。
问题2:兼容XSD 1.0的Schema编写方案
最通用的兼容方案是保持派生类型的粒子结构和基类型完全对齐,不要让外层容器出现单粒子的情况:你只需要在t2的<sequence>中显式声明禁止thing元素出现,补充<xs:element name="thing" minOccurs="0" maxOccurs="0"/>即可,修改后的t2定义如下:
<xs:complexType name="t2"> <xs:complexContent> <xs:restriction base="t1"> <xs:sequence> <xs:element name="thing" minOccurs="0" maxOccurs="0"/> <xs:group ref="stuffGroup" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> </xs:restriction> </xs:complexContent> </xs:complexType>
这种写法下,t2的<sequence>和基类型t1的<sequence>都包含2个粒子,校验逻辑会逐个比对对应位置的粒子:
- 第一个粒子
thing的0~0是基类型0~1的合法限制 - 第二个粒子
stuffGroup的出现范围和基类型完全匹配
完全符合XSD 1.0的规范要求,所有1.0校验工具都可以正常处理。
针对你提到的替换组场景,该方案同样适用:只要保持派生类型的粒子结构层级、数量和基类型完全对齐,将需要禁用的粒子显式设置maxOccurs="0"即可规避单粒子容器展开导致的匹配错误,不需要内联group或者修改替换组定义。
内容的提问来源于stack exchange,提问作者Chapman Flack

