CasaDelGato
CasaDelGato

Reputation: 645

<xs:all minOccurs="0" still requires the elements to exist

I'm writing a Schema for our (old) XML output, and have run into an issue where an element may contain some sub-elements. I'm using an "xs:all minOccurs="0" in the schema, but when I validate against the XML, it's requiring at least one instance of each sub-element.

    <xs:element name="Project">
        <xs:complexType>
            <xs:all minOccurs="0" maxOccurs="1">
                <xs:element ref="lit:ProductPool" minOccurs="1"/>
                <xs:element ref="lit:ProjectDefaults"/>
                <xs:element ref="lit:TaskInfo"/>
            </xs:all>
            <xs:attribute name="Name" type="lit:TextType_2010"/>
... a bunch more

Then when I use that to validate some XML that only has the "ProductPool" sub element, the validator complains that the other 2 are missing and are required.

    Reason: The following elements are expected after this location (see below)
        'lit:TaskInfo'
        'lit:ProjectDefaults'
    Error location: MetrixXML / Project
    Details
        cvc-complex-type.1.4: The content for element <Project> is incomplete.
        cvc-type.3.2: Element <Project> is not valid with respect to type definition '{anonymous}'.
        cvc-elt.5.2.1: The element <Project> is not valid with respect to the actual type definition '{anonymous}'.```

Upvotes: 1

Views: 4379

Answers (2)

Andreas
Andreas

Reputation: 159096

On an <xs:element>*, the value of attributes minOccurs and maxOccurs both default to 1.
On an <xs:all>*, the value of attributes minOccurs and maxOccurs both default to 1.

* Click link to see specification

That means the follow 3 constructs are the same:

<!-- As defined in question -->
<xs:all minOccurs="0" maxOccurs="1">
    <xs:element ref="lit:ProductPool" minOccurs="1"/>
    <xs:element ref="lit:ProjectDefaults"/>
    <xs:element ref="lit:TaskInfo"/>
</xs:all>
<!-- Without specifying values that are same as defaults -->
<xs:all minOccurs="0">
    <xs:element ref="lit:ProductPool"/>
    <xs:element ref="lit:ProjectDefaults"/>
    <xs:element ref="lit:TaskInfo"/>
</xs:all>
<!-- Specifying values, even if same as defaults -->
<xs:all minOccurs="0" maxOccurs="1">
    <xs:element ref="lit:ProductPool" minOccurs="1" maxOccurs="1"/>
    <xs:element ref="lit:ProjectDefaults" minOccurs="1" maxOccurs="1"/>
    <xs:element ref="lit:TaskInfo" minOccurs="1" maxOccurs="1"/>
</xs:all>

This means that if the all is used in the actual XML, by having any of ProductPool, ProjectDefaults, or TaskInfo present, then all 3 must be present.

The minOccurs="0" means that you can have none of them, or all three of them.

Perhaps you believed that minOccurs defaulted to 0, in which case you should have written it like this:

<xs:all minOccurs="0">
    <xs:element ref="lit:ProductPool"/>
    <xs:element ref="lit:ProjectDefaults" minOccurs="0"/>
    <xs:element ref="lit:TaskInfo" minOccurs="0"/>
</xs:all>

With such a definition, ProductPool is optional, and can appear by itself. ProjectDefaults and TaskInfo are also optional, but if either is present, then ProductPool is required. The three elements can appear in any order.

Upvotes: 1

Dijkgraaf
Dijkgraaf

Reputation: 11527

That is because your MinOccurs is on the All node rather than on the ProjectDefaults or TaskInfo, by default they will be minOccurs once. So if ProductPool was not there, it will not complain, but as soon as you have ProductPool, it will expect the other two.

Resolve it by setting MinOccurs = 0 on ProjectDefaults and TaskInfo

Upvotes: 2

Related Questions