Hunt
Hunt

Reputation: 8435

Checkbox kind of fields with XML Schema

I have the following piece of XSD:

<xsd:complexContent>
    <xsd:extension base="mes:Request">
         <xsd:sequence>
           <xsd:element name="empId" type="xsd:string"/>
           <xsd:element name="empTaskId" type="xsd:int"/>
           <xsd:element name="empStateName" type="xsd:string"/>
           <xsd:element name="empTypeName" type="xsd:string"/>
           <xsd:element name="empActionName" type="xsd:string"/>
           <xsd:element name="empTransactionId" type="xsd:int"/>                               
        </xsd:sequence>
    </xsd:extension>
</xsd:complexContent>

What I want, is to allow only one field as mandatory from any of the fields listed into <sequence>. I tried using <choice> but it behaves like radio buttons; I want the functionality of check boxes (1 or more fields - multiple choice).

Can any one help me on how to achieve this?

Upvotes: 1

Views: 2983

Answers (1)

Bogdan
Bogdan

Reputation: 24590

When you start moving into "validation logic" you hit the limitations of XML Schema. XML Schema can't do that so you either need to perform a basic validation with XML Schema in the lower layers of your app an in the upper layers reinforce the logic that XML Schema couldn't handle or move to something with more expressive validation rules.

That aside, the best I can think of enforcing your requirements with XML schema is something like this:

<?xml version="1.0" encoding="utf-8" ?>
<xsd:schema targetNamespace="http://tempuri"
            elementFormDefault="qualified"
            xmlns:t="http://tempuri"
            xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <xsd:element name="Demo">
    <xsd:complexType>
      <xsd:choice minOccurs="1" maxOccurs="6">
        <xsd:element name="empId" type="xsd:string"/>
        <xsd:element name="empTaskId" type="xsd:int"/>
        <xsd:element name="empStateName" type="xsd:string"/>
        <xsd:element name="empTypeName" type="xsd:string"/>
        <xsd:element name="empActionName" type="xsd:string"/>
        <xsd:element name="empTransactionId" type="xsd:int"/>
      </xsd:choice>
    </xsd:complexType>
    <xsd:unique name="unique1">
      <xsd:selector xpath="."/>
      <xsd:field xpath="t:empId"/>
    </xsd:unique>
    <xsd:unique name="unique2">
      <xsd:selector xpath="."/>
      <xsd:field xpath="t:empTaskId"/>
    </xsd:unique>
    <xsd:unique name="unique3">
      <xsd:selector xpath="."/>
      <xsd:field xpath="t:empStateName"/>
    </xsd:unique>
    <xsd:unique name="unique4">
      <xsd:selector xpath="."/>
      <xsd:field xpath="t:empTypeName"/>
    </xsd:unique>
    <xsd:unique name="unique5">
      <xsd:selector xpath="."/>
      <xsd:field xpath="t:empActionName"/>
    </xsd:unique>
    <xsd:unique name="unique6">
      <xsd:selector xpath="."/>
      <xsd:field xpath="t:empTransactionId"/>
    </xsd:unique>
  </xsd:element>
</xsd:schema>

You use the <choice> element to only select one type of element with minOccurs="1" so you can have at least one of it and maxOccurs="6" to have them all. But now you could select the same element more times so you have to restrict that and this is where <unique> comes into play.

But do be aware that this example is not without it's limitations, being that you can't restrict the order of the elements (i.e. reinforce the <sequence> restriction).

Upvotes: 3

Related Questions