4
votes

I am trying to create an XSD schema for the following XML:

<root>
  <!-- The actual file must contain one of the following constraints -->
  <constraint type="interval">
    <min>100</min>
    <max>200</max>
  </constraint>

  <constraint type="equals">
    <value>EOF</value>
  </constraint>
</root>

The child elements of the constraint element depends on the value of the type attribute.

I have successfully validated the XML using an abstract type defining the type attribute, and two extending types defining the child elements. This would require me to decorate the XML with an xsi:type attribute, naming the actual extending type:

  <constraint type="interval" xsi:type="intervalConstraintType">
    <min>100</min>
    <max>200</max>
  </constraint>

Sadly, I'm not in control of the XML-structure and new attributes will be hard to introduce.

Is this doable with XSD? Are there alternatives that are more suitable?

2

2 Answers

0
votes

I think it should be possible, but I currently do not know how to do it myself. As a workaround you could rewrite the xml on the fly to include your extension.

Edit: Hmm, it looks like it is not possible, at least not in XSD 1.0

0
votes

The child elements of the constraint element depends on the value of the type attribute.

I think it could be possible with XSD 1.1, with the use of assertions. Your schema could look something like this (untested)

<!-- ... -->
<xs:element name="constraint"> 
  <xs:complexType> 
     <xs:sequence> 
         <xs:element name="min" type="xs:decimal" minOccurs="0" maxOccurs="1" /> 
         <xs:element name="max" type="xs:decimal" minOccurs="0" maxOccurs="1" />
         <xs:element name="value" type="xs:string"minOccurs="0" maxOccurs="1" />
     </xs:sequence> 
     <xs:attribute name="type" type="contraintType" />

     <xs:assert test="

        if (@type eq 'equals')
        then (exist(value) and empty(min, max))
        else (exist(min) and exist(max) and empty(value))

     "/>

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

<xs:simpleType name="contraintType">
    <xs:restriction base="xs:string">
        <xs:enumeration value="interval"/>
        <xs:enumeration value="equals"/>
    </xs:restriction>
</xs:simpleType>