XML Schema中3个任意顺序元素的约束配置咨询:2个必现1次,1个至少1次
解决XML Schema元素任意排序且满足出现次数约束的方案
嘿,我完全懂你的需求:要让<bio>元素里的三个子元素可以任意顺序排列(包括交替穿插),同时严格保证:
favoriteColor和favoriteNumber必须恰好出现1次comment必须至少出现1次
下面给你两种可行的解决方案,优先推荐更简洁的XSD 1.1方案,如果你需要兼容旧版本的XSD 1.0,也可以用第二种写法。
方案一:XSD 1.1(推荐,简洁高效)
XSD 1.1新增了断言(xs:assert)功能,可以直接约束元素的出现次数,完美解决任意顺序+次数限制的需求:
<xs:element name="bio"> <xs:complexType> <!-- 允许三个元素任意顺序、任意次数重复出现 --> <xs:choice maxOccurs="unbounded"> <xs:element name="favoriteColor" type="xs:string"/> <xs:element name="favoriteNumber" type="xs:int"/> <xs:element name="comment" type="xs:string"/> </xs:choice> <!-- 用断言强制约束每个元素的出现次数 --> <xs:assert test="count(favoriteColor) = 1 and count(favoriteNumber) = 1 and count(comment) >= 1"/> </xs:complexType> </xs:element>
解释:
<xs:choice maxOccurs="unbounded">:让三个元素可以以任意顺序、任意次数出现在<bio>里<xs:assert>:通过XPath表达式精准控制每个元素的出现次数,确保完全符合你的要求
方案二:XSD 1.0(兼容旧版本,写法繁琐)
如果你的环境只能支持XSD 1.0(没有断言功能),就需要枚举所有可能的元素排列组合,同时处理comment可重复的情况:
<xs:element name="bio"> <xs:complexType> <xs:choice> <!-- 情况1:先color→number→至少一个comment --> <xs:sequence> <xs:element name="favoriteColor" type="xs:string"/> <xs:element name="favoriteNumber" type="xs:int"/> <xs:element name="comment" type="xs:string" minOccurs="1" maxOccurs="unbounded"/> </xs:sequence> <!-- 情况2:先color→至少一个comment→number --> <xs:sequence> <xs:element name="favoriteColor" type="xs:string"/> <xs:element name="comment" type="xs:string" minOccurs="1" maxOccurs="unbounded"/> <xs:element name="favoriteNumber" type="xs:int"/> </xs:sequence> <!-- 情况3:先number→color→至少一个comment --> <xs:sequence> <xs:element name="favoriteNumber" type="xs:int"/> <xs:element name="favoriteColor" type="xs:string"/> <xs:element name="comment" type="xs:string" minOccurs="1" maxOccurs="unbounded"/> </xs:sequence> <!-- 情况4:先number→至少一个comment→color --> <xs:sequence> <xs:element name="favoriteNumber" type="xs:int"/> <xs:element name="comment" type="xs:string" minOccurs="1" maxOccurs="unbounded"/> <xs:element name="favoriteColor" type="xs:string"/> </xs:sequence> <!-- 情况5:先至少一个comment→color→number --> <xs:sequence> <xs:element name="comment" type="xs:string" minOccurs="1" maxOccurs="unbounded"/> <xs:element name="favoriteColor" type="xs:string"/> <xs:element name="favoriteNumber" type="xs:int"/> </xs:sequence> <!-- 情况6:先至少一个comment→number→color --> <xs:sequence> <xs:element name="comment" type="xs:string" minOccurs="1" maxOccurs="unbounded"/> <xs:element name="favoriteNumber" type="xs:int"/> <xs:element name="favoriteColor" type="xs:string"/> </xs:sequence> <!-- 情况7:comment穿插在color和number之间(比如comment→color→comment→number) --> <xs:sequence> <xs:element name="comment" type="xs:string" minOccurs="1"/> <xs:element name="favoriteColor" type="xs:string"/> <xs:element name="comment" type="xs:string" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="favoriteNumber" type="xs:int"/> <xs:element name="comment" type="xs:string" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> <!-- 情况8:comment穿插在number和color之间(比如comment→number→comment→color) --> <xs:sequence> <xs:element name="comment" type="xs:string" minOccurs="1"/> <xs:element name="favoriteNumber" type="xs:int"/> <xs:element name="comment" type="xs:string" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="favoriteColor" type="xs:string"/> <xs:element name="comment" type="xs:string" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> </xs:choice> </xs:complexType> </xs:element>
注意:
这种写法虽然能满足需求,但需要枚举所有可能的排列组合,代码冗余且维护起来很麻烦,所以如果环境支持,优先选XSD 1.1的方案。
内容的提问来源于stack exchange,提问作者Benjamin Kershner
相关产品推荐
相关产品推荐

