如何用XSD校验含必填元素且允许任意位置其他元素的XML?
问题:编写XSD校验XML包含指定必填元素,同时允许任意位置的额外元素
需要编写XSD实现以下校验逻辑:
- XML的
<HEAD>元素下必须包含<thing1>、<thing2>、<thing3>三个元素,顺序无关 - 允许
<HEAD>中添加任意其他元素(如<thing4>、<thing5>),且这些元素可以出现在任意位置 - 此前找到的方案仅支持额外元素放在末尾,无法满足需求
- 尝试将
<xsd:all>与<xsd:any>组合使用,但未成功
合法示例1:
<HEAD> <thing1>Str123</thing1> <thing2>Str123</thing2> <thing3>Str123</thing3> </HEAD>
合法示例2:
<HEAD> <thing1>Str123</thing1> <thing2>Str123</thing2> <thing4>Str123</thing4> <thing3>Str123</thing3> <thing5>Str123</thing5> </HEAD>
可行方案
方案1:XSD 1.1(推荐,实现更简洁)
XSD 1.1放宽了<xs:all>的限制,允许包含<xs:any>,同时支持断言(xs:assert)实现复杂校验逻辑。
方法A:<xs:all> + <xs:any>组合
直接在<xs:all>中定义必填元素,同时加入<xs:any>允许任意其他元素,设置processContents="lax"避免校验未定义的额外元素:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" version="1.1"> <xs:element name="HEAD"> <xs:complexType> <xs:all> <!-- 必填元素,minOccurs="1"确保必须出现至少一次 --> <xs:element name="thing1" type="xs:string" minOccurs="1"/> <xs:element name="thing2" type="xs:string" minOccurs="1"/> <xs:element name="thing3" type="xs:string" minOccurs="1"/> <!-- 允许任意数量的其他元素,可出现在任意位置 --> <xs:any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/> </xs:all> </xs:complexType> </xs:element> </xs:schema>
方法B:使用断言(xs:assert)
如果需要更灵活的校验规则(比如限制必填元素出现次数),可以用断言直接检查元素存在性:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" version="1.1"> <xs:element name="HEAD"> <xs:complexType> <!-- 允许任意顺序、任意数量的元素 --> <xs:sequence> <xs:any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> <!-- 断言强制三个必填元素至少各出现一次 --> <xs:assert test="count(thing1) >= 1 and count(thing2) >= 1 and count(thing3) >= 1"/> </xs:complexType> </xs:element> </xs:schema>
方案2:XSD 1.0(兼容旧环境)
XSD 1.0中<xs:all>不允许包含<xs:any>,也不支持断言,可通过<xs:choice>配合maxOccurs="unbounded"模拟需求:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:element name="HEAD"> <xs:complexType> <xs:choice maxOccurs="unbounded"> <!-- 必填元素,minOccurs="1"确保至少出现一次 --> <xs:element name="thing1" type="xs:string" minOccurs="1"/> <xs:element name="thing2" type="xs:string" minOccurs="1"/> <xs:element name="thing3" type="xs:string" minOccurs="1"/> <!-- 允许任意其他元素 --> <xs:any namespace="##any" processContents="lax" minOccurs="0"/> </xs:choice> </xs:complexType> </xs:element> </xs:schema>
这种方式通过循环选择元素,既保证必填元素至少出现一次,又允许任意顺序插入额外元素。
内容的提问来源于stack exchange,提问作者user16038501
相关产品推荐
相关产品推荐

