0

I'm trying to create a XSD to validate this kind of XML:

<Upload>
  <DocumentData>
      <docid>123</docid>
      <domain>PNI</domain>
      <expiry_date>20150101101010</expiry_date>
      <name>orçamento.xlsx</name>
      <type>orçamento</type>
      <user>nmsanto</user>
      <file>fdsfjdflkdsçlfd</file>
      <comments></comments>
  </DocumentData>
  <DocumentAttributes>
      <projectid>123</projectid>
      <objectid>1</objectid>
      <keyword1>Nuno</keyword1>
      <keyword1>Rua xpto</keyword1>
      <keyword2>1223-123</keyword2>
      <keyword3>Lisboa</keyword3>
  </DocumentAttributes>
 </Upload>

The XML must always have the element Upload with the elements DocumentData and DocumentAttributes. In DocumentData the elements domain, name, type, user and file are mandatory and can only show up one time, while the others are optional. The most difficulty I'm having is with the DocumentAttributes element. There has to be at least one of either projectid or objectid, keyword1-keyword6 are optional and there can be 4 more optional elements with any name.

So far the XSD I have is this one:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
attributeFormDefault="unqualified" elementFormDefault="qualified">
<xs:element name="Upload">
    <xs:complexType>
        <xs:all>
            <xs:element name="DocumentData">
                <xs:complexType>
                    <xs:all>
                        <xs:element name="docid" type="xs:string" minOccurs="0" />
                        <xs:element name="domain" type="xs:string" />
                        <xs:element name="versao" type="xs:integer" minOccurs="0" />
                        <xs:element name="name" type="xs:string" />
                        <xs:element name="expiry_date" type="xs:string" />
                        <xs:element name="type" type="xs:string" />
                        <xs:element name="user" type="xs:string" />
                        <xs:element name="file" type="xs:string" />
                        <xs:element name="comments" type="xs:string"
                            minOccurs="0" />
                    </xs:all>
                </xs:complexType>
            </xs:element>
            <xs:element name="DocumentAttributes">

                <xs:complexType>
                    <xs:all>
                        <xs:element type="xs:string" minOccurs="0" />
                        <xs:element type="xs:string" minOccurs="0" />
                        <xs:element type="xs:string" minOccurs="0" />
                        <xs:element type="xs:string" minOccurs="0" />
                        <xs:element name="keyword1" type="xs:string"
                            minOccurs="0" />
                        <xs:element name="keyword2" type="xs:string"
                            minOccurs="0" />
                        <xs:element name="keyword3" type="xs:string"
                            minOccurs="0" />
                        <xs:element name="keyword4" type="xs:string"
                            minOccurs="0" />
                        <xs:element name="keyword5" type="xs:string"
                            minOccurs="0" />
                        <xs:element name="keyword6" type="xs:string"
                            minOccurs="0" />
                            <xs:element name="usetype" abstract="true" />
                <xs:element name="projectid" substitutionGroup="usetype" />
                <xs:element name="objectid" substitutionGroup="usetype" />
                    </xs:all>
                </xs:complexType>



            </xs:element>
        </xs:all>
    </xs:complexType>
</xs:element>

I have tried putting a choice element inside the all element to validate the objectid/projectid but I've learned that it isn't possible to do so. How would I go about validating that?

  • 1
    In comparison with `xs:sequence` and `xs:choice`, `xs:all` has some limitations; but `xs:all` is for situations in which some elements can appear in any order, if the order of your elements is fixed you can use `xs:sequence` instead, which can contain `xs:choice`. – lfurini Apr 16 '15 at 17:22
  • Thank you for your response. I am aware of xs:sequence but in my case the elements can come in any order. – RicardoDeus Apr 20 '15 at 14:16

1 Answers1

0

Try the following code if it suits your problem.

All the children of <DocumentData> can appear in any order but in in <DocumentAttributes> the <projectid> and <objectid> elements must be before keywords. Max 4 keywords are allowed.

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

<xs:element name="Upload">
    <xs:complexType>
        <xs:sequence>
            <xs:element name="DocumentData">
                <xs:complexType>
                    <xs:all>
                        <xs:element name="docid" type="xs:string" minOccurs="0" />
                        <xs:element name="domain" type="xs:string" />
                        <xs:element name="versao" type="xs:integer" minOccurs="0" />
                        <xs:element name="name" type="xs:string" />
                        <xs:element name="expiry_date" type="xs:string" />
                        <xs:element name="type" type="xs:string" />
                        <xs:element name="user" type="xs:string" />
                        <xs:element name="file" type="xs:string" />
                        <xs:element name="comments" type="xs:string" minOccurs="0" />
                    </xs:all>
                </xs:complexType>
            </xs:element>
            <xs:element name="DocumentAttributes">
                <xs:complexType>
                    <xs:sequence>
                        <xs:choice>
                            <xs:sequence>
                                <xs:element name="projectid" type="xs:string" />
                                <xs:element name="objectid" type="xs:string" minOccurs="0" />
                            </xs:sequence>
                            <xs:sequence>
                                <xs:element name="objectid" type="xs:string" />
                                <xs:element name="projectid" type="xs:string" minOccurs="0" />
                            </xs:sequence>
                        </xs:choice>
                        <xs:choice minOccurs="0" maxOccurs="4">
                            <xs:element name="keyword1" type="xs:string" minOccurs="0" />
                            <xs:element name="keyword2" type="xs:string" minOccurs="0" />
                            <xs:element name="keyword3" type="xs:string" minOccurs="0" />
                            <xs:element name="keyword4" type="xs:string" minOccurs="0" />
                            <xs:element name="keyword5" type="xs:string" minOccurs="0" />
                            <xs:element name="keyword6" type="xs:string" minOccurs="0" />
                        </xs:choice>
                    </xs:sequence>
                </xs:complexType>
            </xs:element>
        </xs:sequence>
    </xs:complexType>
</xs:element>

</xs:schema>
jasso
  • 13,736
  • 2
  • 36
  • 50
  • I'm having some troubles adding the possibility of having 4 elements which can have any name to the DocumentAttributes. I have tried using the element "any" but I am getting an error saying ambiguity could be created both inside one of the "choice" elements or outside. Do you have any idea on how to solve this? Thank you in advance! – RicardoDeus Apr 21 '15 at 10:02
  • The result becomes ambiguous because both the optional projectid/obectid or the keyword elements match `any` element declaration. Some simple solutions could be 1) to make both objectid and projectid mandatory 2) require any elements to be in a different namespace or 3) wrap the any elements inside a `` element. Solution #3 probably is the most clear one. – jasso Apr 24 '15 at 14:15