XMLSpy ignores "minOccurs"? Why is this XML valid?
Please enlighten me why XML Spy thinks this is valid. FYI, this specifies an SQL query. Here the XML:
<sideBar title="LabelSearch">
<searchLabel table="ID=*.companies">
<filter accessRight="r">
<and>
<filterElement argument="companies.Type" operator="=" value="Client"/>
</and>
</filter>
</searchLabel>
</sideBar>
The problem: I should not be allowed to put in only one filterElement inside the "and" tag, but at least two. If I only have one filterElement, I should use it without the surrounding "and" tag. Here the XSD:
<xs:complexType name="filterGroupType">
<xs:sequence>
<xs:choice>
<xs:element name="or" type="filterGroupOrType"/>
<xs:element name="and" type="filterGroupAndType"/>
<xs:element name="filterElement" type="filterType"/>
</xs:choice>
</xs:sequence>
<xs:attribute name="accessRight" type="accessRightSimpleType" use="required"/>
</xs:complexType>
<xs:complexType name="filterGroupAndType">
<xs:sequence minOccurs="2" maxOccurs="unbounded">
<xs:element name="or" type="filterGroupOrType" minOcc开发者_开发知识库urs="0"/>
<xs:element name="filterElement" type="filterType" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="filterGroupOrType">
<xs:sequence minOccurs="2" maxOccurs="unbounded">
<xs:element name="and" type="filterGroupAndType" minOccurs="0"/>
<xs:element name="filterElement" type="filterType" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="filterType">
<xs:attribute name="argument" type="xs:string" use="required"/>
<xs:attribute name="operator" type="operatorSimpleType" use="required"/>
<xs:attribute name="value" type="xs:anySimpleType"/>
<xs:attribute name="field" type="fieldTitleSimpleType"/>
</xs:complexType>
Thanks in advance.
Briefly
- Document is valid because elements have
minOccurs="0"
. - Use
<xs:choice>
instead of<xs:sequence>
.
A bit longer answer.
Just like @Damien said, that XML is valid because this part of your schema allows "empty" sequences.
<xs:sequence minOccurs="2" maxOccurs="unbounded">
<xs:element name="or" type="filterGroupOrType" minOccurs="0"/>
<xs:element name="filterElement" type="filterType" minOccurs="0"/>
</xs:sequence>
With <xs:sequence minOccurs="2" maxOccurs="unbounded">
You define that "this sequence must appear at least twice". At the same time <xs:element name="or" type="filterGroupOrType" minOccurs="0"/>
Allows these elements within the sequence to be absent. Metaphorically it is like saying "You must order a meal twice but you don't have to eat any of the meals you ordered."
Instead if you want to always have at least 2 child elements and these children can be<filterElement>
or <or>
elements in any order, you should use <xs:choice>
with minOccurs="1"
<xs:choice minOccurs="2" maxOccurs="unbounded">
<xs:element name="or" type="filterGroupOrType" minOccurs="1"/>
<xs:element name="filterElement" type="filterType" minOccurs="1"/>
</xs:choice>
The default value for minOccurs
is 1 so you can leave it out and keep your code cleaner and shorter. <xs:choice>
selects one of its children and repeats choosing at least minOccurs
times. If at least one of choices can has minOccurs="0"
then the choice will also allow "empty" selections.
You have a minOccurs="0" on filterElement. So a single filterElement can be seen as a filterElement 0 times, followed by a filterElement. A valid sequence. Maybe you should avoid mixing minOccurs in xs:sequence and xs:element in your schema...
You have a sequence that must occur twice, but elements in the sequence are optional (minOccurs="0"). The sequence itself doesn't represent any XML, it just defines the possible elements it can contain and the order they must be in. A perfectly valid sequence can be empty in that case.
Replacing <xs:sequence> with <xs:choice> and changing minOccurs to 1 on the subelements will work if you do not care what order the elements appear in and it looks like you don't. If you don't set minOccurs to 1 on the children then a valid choice would still be the element occurring 0 times and your XML would validate. If you set minOccurs to 2 on the child elements then you would have a minimum of 4 elements since you would make a choice twice and pick from each child element occurring twice each time.
精彩评论