Ulf Tietze
Ulf Tietze

Reputation: 57

XSD for optional list of at least one element?

I want to make sure, that <specials/> can be optional, but when it occurs, I want to make sure, that it has at least one <special>.

Imagine the following XML:

<software>
  <programm id="123">
    <name>Editor</name>
    <specials>
      <special>Something really special here</special>
      <special>Something special as well</special>
    </specials>
  </programm>
  <programm id="456">
    <name>Another Editor</name>
  </programm>
</software>

My tried XSD for this is. This won't throw a validation error, if there is just <specials></specials> but no children inside.

<xs:element name="software">
    <xs:complexType>
        <xs:sequence>
            <xs:element name="programm" minOccurs="0" maxOccurs="unbounded">
                <xs:complexType>
                    <xs:sequence>
                        <xs:element name="name" type="xs:string" minOccurs="1"/>
                        <xs:element name="specials" minOccurs="0">
                            <xs:complexType>
                                <xs:sequence minOccurs="1">
                                    <xs:element name="special" type="xs:string" minOccurs="1"/>
                                </xs:sequence>
                            </xs:complexType>
                        </xs:element>
                    </xs:sequence>
                    <xs:attribute name="id" type="programmID"/>
                </xs:complexType>
            </xs:element>
       </xs:sequence>
    </xs:complexType>
</xs:element>

Upvotes: 2

Views: 766

Answers (1)

kjhughes
kjhughes

Reputation: 111726

An XSD constraint for an optional list element of at least one member element can be expressed simply with minOccurs and maxOccurs:

          <xs:element name="list" minOccurs="0">
            <xs:complexType>
              <xs:sequence>
                <xs:element name="member" maxOccurs="unbounded"/>
              </xs:sequence>
            </xs:complexType>
          </xs:element>

This won't throw a validation error, if there is just <specials></specials> but no children inside.

On the contrary, your XSD as written will fail to validate XML with an empty specials element as desired because it specifies that specials is optional but when present, its special child element must occur once. In addition to this analytical observation, I have confirmed this behavior empirically via actual validation.

Side notes:

  • minOccurs="1" is the default, so you can remove those throughout your XSD.

  • maxOccurs="1" is the default, so you probably want maxOccurs="unbounded" on special to allow its repetition within specials.

  • You do not need occurrence constraints on xs:sequence here. Besides minOccurs="1" already being the default, there's only a single child in the sequence anyway, so it's unnecessary (and arguably distracting) to specify a group of one's occurrence constraints.

Here is a complete XSD that incorporates the above notes and validates your XML:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           elementFormDefault="qualified">
  <xs:element name="software">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="programm" minOccurs="0" maxOccurs="unbounded">
          <xs:complexType>
            <xs:sequence>
              <xs:element name="name" type="xs:string"/>
              <xs:element name="specials" minOccurs="0">
                <xs:complexType>
                  <xs:sequence>
                    <xs:element name="special" maxOccurs="unbounded"/>
                  </xs:sequence>
                </xs:complexType>
              </xs:element>
            </xs:sequence>
            <xs:attribute name="id" type="xs:string"/>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

See also

Upvotes: 1

Related Questions