You can achieve that with a combination of sequence
and choice
repeating the elements in the several possible combinations, to guarantee that the required ones are present, but it won't be so nice and simple. I would suggest a different design (if possible).
Is there any reason your <chunks>
elements can appear anywhere? If you are designing the XML, deciding upon which restrictions are actually necessary and which ones should be made flexible will simplify generation and processing (as well as validation). Keeping them in a sequence or wrapping them will allow them to be seen as a group
and will make validation easier (it would also simplify language mapping, for example, wrapped identical elements are frequently mapped as an array).
One form of keeping the similar elements together is sequence
, which you don't want. Another would be to wrap it in a type and use xs:all
:
<xs:element name="example">
<xs:complexType>
<xs:all>
<xs:element name="filename" type="xs:string" minOccurs="1" maxOccurs="1"/>
<xs:element name="hostname" type="xs:string" minOccurs="0" maxOccurs="1"/>
<xs:element name="chunks" type="ChunksType" minOccurs="1" maxOccurs="1"/>
</xs:all>
</xs:complexType>
</xs:element>
<xs:complexType name="ChunksType">
<xs:sequence>
<xs:element name="chunk" minOccurs="1" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
This would validate a XML fragment like this:
<example>
<chunks>
<chunk>...</chunk>
<chunk>...</chunk>
</chunks>
<filename>...</filename>
</example>
<!-- -->
<example>
<filename>...</filename>
<chunks>
<chunk>...</chunk>
<chunk>...</chunk>
</chunks>
</example>
<!-- -->
<example>
<filename>...</filename>
<chunks>
<chunk>...</chunk>
</chunks>
<hostname>...</hostname>
</example>
<example>
<hostname>...</hostname>
<filename>...</filename>
<chunks>
<chunk>...</chunk>
<chunk>...</chunk>
</chunks>
</example>
And fail for these:
<!-- missing filename -->
<example>
<chunks>
<chunk>...</chunk>
<chunk>...</chunk>
</chunks>
</example>
<!-- no chunks block -->
<example>
<filename>...</filename>
<hostname>...</hostname>
</example>
<!-- empty chunks block -->
<example>
<hostname>...</hostname>
<filename>...</filename>
<chunks></chunks>
</example>
You can't just place your unbounded
element in xs:all
since it only allows 0
or 1
. You can't use a sequence of choices because you have required elements. And you can't combine xs:all
with sequence
which would solve your problem (actually you can do some of these things, but if you are using XSD 1.1).
In XSD 1.1 you can have xs:all
with unbounded
elements so you could validate your XML using:
<xs:all>
<xs:element name="filename" type="xs:string" minOccurs="1" maxOccurs="1"/>
<xs:element name="hostname" type="xs:string" minOccurs="0" maxOccurs="1"/>
<xs:element name="chunks" type="xs:string" minOccurs="1" maxOccurs="unbounded"/>
</xs:all>
which would be illegal in XSD 1.0.