5

I have the following element in my XSD:

<xs:element name="documents" minOccurs="1" maxOccurs="1">
    <xs:complexType>
        <xs:sequence>

            <xs:element name="invoice" minOccurs="1" maxOccurs="1">
                <xs:simpleType>
                    <xs:restriction base="xs:string">
                        <xs:minLength value="1"/>
                    </xs:restriction>
                </xs:simpleType>
            </xs:element>

            <xs:element name="report" minOccurs="0" maxOccurs="1">
                <xs:simpleType>
                    <xs:restriction base="xs:string">
                        <xs:minLength value="1"/>
                    </xs:restriction>
                </xs:simpleType>
            </xs:element>

            <xs:element name="additional" minOccurs="0" maxOccurs="unbounded">
                <xs:simpleType>
                    <xs:restriction base="xs:string">
                        <xs:minLength value="1"/>
                    </xs:restriction>
                </xs:simpleType>
            </xs:element>

        </xs:sequence>
    </xs:complexType>
</xs:element>

You can see that documents must always have an invoice and optionally it can have a single report and zero or more additionals.

The problem is that these elements can have a different order of appearance, so I can´t use a sequence anymore. I tried to use all but then the problem is the additional element, since it has maxOccurs="unbounded".

How can I have an unordered list of elements with one of those those elements being always required and another element having unlimited occurrences?

kjhughes
  • 106,133
  • 27
  • 181
  • 240
ivan0590
  • 1,229
  • 11
  • 18

1 Answers1

4

Three suggestions. Either:

  1. Impose an ordering. Almost always the perceived need to allow any ordering of elements is unnecessary in practice.
  2. Use XSD 1.1, where maxOccurs="unbounded" is supported on xsd:all.
  3. Use a wrapper around the element you wish to allow to have maxOccurs="unbounded". See additionalList in the XSD below for a working example.

XSD with wrapper element to work around unbounded xsd:all limitation

<?xml version="1.0" encoding="utf-8" standalone="no"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
           elementFormDefault="qualified">
  <xs:element name="documents">
    <xs:complexType>
      <xs:all>
        <xs:element name="invoice" minOccurs="1" maxOccurs="1">
          <xs:simpleType>
            <xs:restriction base="xs:string">
              <xs:minLength value="1"/>
            </xs:restriction>
          </xs:simpleType>
        </xs:element>
        <xs:element name="report" minOccurs="0" maxOccurs="1">
          <xs:simpleType>
            <xs:restriction base="xs:string">
              <xs:minLength value="1"/>
            </xs:restriction>
          </xs:simpleType>
        </xs:element>
        <xs:element name="additionalList" minOccurs="0">
          <xs:complexType>
            <xs:sequence>
              <xs:element name="additional" minOccurs="0" maxOccurs="unbounded">
                <xs:simpleType>
                  <xs:restriction base="xs:string">
                    <xs:minLength value="1"/>
                  </xs:restriction>
                </xs:simpleType>
              </xs:element>
            </xs:sequence>
          </xs:complexType>
        </xs:element>
      </xs:all>
    </xs:complexType>
  </xs:element>
</xs:schema>
kjhughes
  • 106,133
  • 27
  • 181
  • 240
  • I would like to use a wrapper but right now I can't modify the xml structure. And sadly in this case the order can't be always the same. I would like to keep the `sequence` but I can't. – ivan0590 Jun 22 '16 at 14:31
  • I assume then that you cannot impose an ordering? Then go to XSD 1.1 where `maxOccurs="unbounded"` is supported on `xsd:all`. – kjhughes Jun 22 '16 at 14:35
  • How can I switch to 1.1? – ivan0590 Jun 22 '16 at 14:36
  • Check that your validating parser supports XSD 1.1, or that you're able to switch to one that does. – kjhughes Jun 22 '16 at 14:55
  • I'm using the XML Tools plugin for Notepad++. I don't know what validation parser could do the trick. Like you can imagine I'm a big XSD noob :( – ivan0590 Jun 22 '16 at 15:01
  • As an XSD noob, I'd strongly suggest that you use `xs:sequence` rather than `xs:all` so that you can stick with XSD 1.0. XSD 1.1 support is far from ubiquitous. Notepad++ doesn't support it, nor does Python, Microsoft libraries, etc. You'd need something like Saxon, Xerces, or Altova. – kjhughes Jun 22 '16 at 15:08
  • I see your point, really, but the case is that this is not something I can choose. Trust me, I would be delighted to mantain the `sequence` but I need to validate the xsd against an xml out of my control. The people that send me the xml give me an unordered list of documents and they can't change their system. I will investigate the validation parsers you mentioned. – ivan0590 Jun 22 '16 at 15:30