How to add conditional validation in XSD :

user2432281 picture user2432281 · May 29, 2013 · Viewed 12.5k times · Source

Existing XSD Snippet:

<xs:element name="searchcriteria">
   <xs:complexType>
     <xs:sequence>  
       <xs:element ref="filter" 
                   minOccurs="0" 
                   maxOccurs="unbounded" />
     </xs:sequence>
     <xs:attribute name="Request" 
                   type="RequestType" />
   </xs:complexType>
 </xs:element>  


<xs:element name="filter">
   <xs:complexType>
     <xs:sequence>
       <xs:element ref="filter" 
                   minOccurs="0" 
                   maxOccurs="unbounded" />
     </xs:sequence>
     <xs:attribute name="FieldName" 
                   type="FieldNameType" />
    </xs:complexType>
 </xs:element>

...

  • RequestType : Enumeration of 2 values R1 and R2

  • FieldNameType : Enumeration of 2 values F1, and F2

Now i want to modify this XSD to provide a validation that :

  1. When RequestType = R1, Then Alowed Fields names are F1 and F2
  2. When Request Type = R2, Then allowed Fields names are F1, F3 and F4. ( May be a new enumeration is required)

How can i add such validations ? Thanks.

Answer

C. M. Sperberg-McQueen picture C. M. Sperberg-McQueen · Jun 2, 2013

The basic idea of XSD (and most other XML schema languages) is to bind validation behavior to element types. If you want one set of instances validated one way and another set of instances validated another way (goes the idea), it's prima facie evidence that they are actually two distinct types of elements, and should have two distinct names.

So the simplest way to make XSD validate your requests as you describe is to replace your searchcriteria element with a pair of elements named R1 and R2. Declare them with different types, as you wish: either they each have an element named filter with an attribute carrying an appropriate enumerated type, or R1 is declared as having either an F1 or an F2 as a child, and R2 is declared as having a choice of F1, F3, or F4.

If you can't or won't do this, you can use XSD 1.1 and its conditional type assignment feature to declare two types for searchcriteria (the two types you would otherwise have used for R1 and R2) and assign the appropriate type based on the value of the Request attribute. You can also use assertions on searchcriteria to check the co-constraint.

If you don't have access to an XSD 1.1 validator, tell the vendor of your XSD 1.0 validator that you'd like an upgrade, and explore the use of Schematron assertions to check the constraint.

See also this essentially similar question for more concrete discussion of the options, with examples.