如何在XSD中定义元素OR逻辑?无法修改旧结构
如何在XSD文件中定义元素的OR逻辑?
- 无法修改“OLD STYLE BLOCK”结构,只能扩展现有XML结构
- 尝试编写的XSD出现解析错误,原本希望在
xs:complexType中同时使用xsd:choice和xs:sequence - 能否通过
Version="2.0"为XSD添加额外逻辑?
示例XML
<?xml version="1.0"?> <MyStruct Version="2.0"> <!-- xs should allow "NEW STYLE BLOCK" OR "OLD STYLE BLOCK" with array of id --> <!-- one of them should present !!!! --> <!-- NEW STYLE BLOCK my complex type--> <IDArray> <IDSet> <ID>89</ID> <ID>1</ID> <ID>2</ID> </IDSet> <IDSet> <ID>3</ID> <ID>4</ID> </IDSet> </IDArray> <!-- end of NEW STYLE BLOCK --> <!-- OLD STYLE BLOCK array of elements --> <ID>5</ID> <ID>7</ID> <!-- end of OLD STYLE BLOCK --> <Type>Some type</Type> <!-- mandatory element --> <ReadableName>Human readable name</ReadableName> <!-- mandatory element --> </MyStruct>
拟议的XSD
<?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" version="1.1"> <xs:element name="MyStruct"> <xs:complexType> <xs:choice> <xs:element name="IDArray" minOccurs="0" maxOccurs="1"> <xs:complexType> <xs:choice maxOccurs="unbounded"> <xs:element name="IDSet" minOccurs="1" maxOccurs="unbounded"> <xs:complexType> <xs:choice maxOccurs="unbounded"> <xs:element name="ID" minOccurs="1" maxOccurs="unbounded" /> </xs:choice> </xs:complexType> </xs:element> </xs:choice> </xs:complexType> </xs:element> <xs:element name="ID" minOccurs="0" maxOccurs="unbounded" /> </xs:choice> <xs:sequence> <xs:element name="Type" type="xs:string" /> <xs:element name="ReadableName" type="xs:string" /> </xs:sequence> <!-- error in this line --> <xs:attribute name="Version" type="xs:string" /> </xs:complexType> </xs:element> </xs:schema>
错误信息
./MyStruct.xsd:: element sequence: Schemas parser error : Element '{http://www.w3.org/2001/XMLSchema}complexType': The content is not valid. Expected is (annotation?, (simpleContent | complexContent | ((group | all | choice | sequence)?, ((attribute | attributeGroup)*, anyAttribute?)))).
问题分析与解决方案
1. 解析错误原因
XSD的xs:complexType内容模型规则明确:顶层只能包含一个内容模型容器(choice/sequence/all/group等),不能直接并列choice和sequence,你的写法违反了这个规则,因此报错。
2. 正确实现OR逻辑的XSD
要实现「IDArray(新结构)OR 多个ID(旧结构)二选一,同时必须包含Type和ReadableName」的需求,需要把choice和sequence包裹在一个外层sequence中,并给choice设置minOccurs="1"确保二选一:
<?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" version="1.1"> <xs:element name="MyStruct"> <xs:complexType> <!-- 外层sequence:先选IDArray或多个ID,再必须出现Type和ReadableName --> <xs:sequence> <!-- choice设置minOccurs="1",确保二选一 --> <xs:choice minOccurs="1" maxOccurs="1"> <xs:element name="IDArray"> <xs:complexType> <!-- IDSet为有序重复,用sequence更合理 --> <xs:sequence maxOccurs="unbounded"> <xs:element name="IDSet"> <xs:complexType> <!-- ID为有序重复,用sequence --> <xs:sequence maxOccurs="unbounded"> <xs:element name="ID" type="xs:string" /> </xs:sequence> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="ID" type="xs:string" minOccurs="1" maxOccurs="unbounded" /> </xs:choice> <!-- 必须出现的Type和ReadableName --> <xs:sequence> <xs:element name="Type" type="xs:string" /> <xs:element name="ReadableName" type="xs:string" /> </xs:sequence> </xs:sequence> <xs:attribute name="Version" type="xs:string" /> </xs:complexType> </xs:element> </xs:schema>
3. 利用Version属性添加额外逻辑(XSD 1.1特性)
如果需要根据Version属性区分允许的结构(比如仅Version="2.0"允许新结构,旧版本只能用旧结构),可以使用XSD 1.1的xs:assert断言:
<?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" version="1.1"> <xs:element name="MyStruct"> <xs:complexType> <xs:sequence> <xs:choice minOccurs="0" maxOccurs="1"> <xs:element name="IDArray"> <xs:complexType> <xs:sequence maxOccurs="unbounded"> <xs:element name="IDSet"> <xs:complexType> <xs:sequence maxOccurs="unbounded"> <xs:element name="ID" type="xs:string" /> </xs:sequence> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> </xs:element> </xs:choice> <xs:element name="ID" type="xs:string" minOccurs="0" maxOccurs="unbounded" /> <xs:sequence> <xs:element name="Type" type="xs:string" /> <xs:element name="ReadableName" type="xs:string" /> </xs:sequence> </xs:sequence> <xs:attribute name="Version" type="xs:string" use="required" /> <!-- 断言逻辑:Version="2.0"时可选IDArray或ID;旧版本只能用ID --> <xs:assert test="(Version='2.0' and (IDArray or ID)) or (Version!='2.0' and ID and not(IDArray))"/> <!-- 确保至少有一个ID相关结构 --> <xs:assert test="IDArray or ID"/> </xs:complexType> </xs:element> </xs:schema>
注意:XSD 1.1需要支持该版本的解析器(如Apache Xerces2 2.12+、Saxon等)。
内容的提问来源于stack exchange,提问作者Vlad
相关产品推荐
相关产品推荐

