Search code examples
xmlxsdxerces

XSD - Elements in any order and count (XML validated by XERCES using XSD)


I have problem with XML schema. I need inside one element elements of three types but without any other restriction, followed by exactly one occurrence of element output:

<command path="app.exe" workingDir="/usr/local/bin">
    <param name="--name" assign="=">anyName</param>
    <switch name="--verbose"/>
    <param name="--config">/etc/app/conf.txt</param>
    <param name="--overriding">~/app/conf.txt</param>
    <switch name="-d"/>
    <param name="--report" assign="=">~/app/report.txt</param>
    <param name="--template">~/app/templates/default.tt</param>
    <string>../t/${testName}/log.txt</string>
    <output>
        <out path="stdout.txt"/>
        <err path="stderr.txt"/>
    </output>
</command>

I can use just sequence, all or choice, but no one of them satisfies my requirement. Sequence - any number of times in exact order. All - zero or one times in any order. Choice - only one of them. I have found one solution on this web, but it does not work with Xerces. I try this:

<xs:complexType name="commandType">
    <xs:sequence>
        <xs:group ref="gupa"/>
        <xs:element name="output" type="outputType" minOccurs="1" maxOccurs="1"/>
    </xs:sequence>
    <xs:attribute name="path" use="required" type="value"/>
    <xs:attribute name="workingDir" use="required" type="value"/>
</xs:complexType>

<xs:group name="gupa">
    <xs:choice>
        <xs:element name="env" type="pair" minOccurs="0" maxOccurs="unbounded"/>
        <xs:element name="param" type="paramType" minOccurs="0" maxOccurs="unbounded"/>
        <xs:element name="switch" type="switchType" minOccurs="0" maxOccurs="unbounded"/>
        <xs:element name="string" type="value" minOccurs="0" maxOccurs="unbounded"/>
    </xs:choice>
</xs:group>

But I get the error: Invalid content was found starting with element 'switch'. One of '{param, output}' is expected. There is a trick.

If maxOccurs="unbounded" is moved from elements to element choice in schema, then can any of elements appear in any order in any number of times.

However, when I do it, I get the error: Attribute 'maxOccurs' cannot appear in element 'choice'

I cruised cross the Internet, but I still haven't found what I'm looking for.


Solution

  • You can put the three element types in a choice and then put the choice in a sequence in another sequence.

      <xs:group name="mygr">
        <xs:choice>
          <xs:element name="string"></xs:element>
          <xs:element name="param"></xs:element>
          <xs:element name="switch"></xs:element>
          <xs:element name="env"></xs:element>
        </xs:choice>
      </xs:group>
    
      <xs:element name="root">
        <xs:complexType>
          <xs:sequence >
            <xs:sequence minOccurs="1" maxOccurs="unbounded">
              <xs:group ref="mygr"/>
            </xs:sequence>
            <xs:element name="output"></xs:element>
          </xs:sequence>
        </xs:complexType>
      </xs:element>
    

    Which is what you already had, but the output is taken a level higher.