Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Conditional required elements in an XSD

I have a requirement for an xml schema which accepts either a request with the customer or with the customer id. If the customer Id is 0 then we need the customer data, if it's > 0 then customer data is optional (They can submit ammendements). My XSD looks like this at the moment;

<xs:complexType>


    <xs:any>
      <xs:element name="UserID" type="xs:string" minOccurs="1"/>
      <xs:element name="Password" type="xs:string" minOccurs="1"/>
      <xs:element name="ReferenceNumber" type="xs:string" minOccurs="0"  maxOccurs="1"/>
      <xs:element name="CustomerId" minOccurs="1" maxOccurs="1" type="xs:integer"/>
      <xs:element ref="WhereSigned"/>
      <xs:element name="ContactName" type="xs:string" minOccurs="0"  maxOccurs="1"/>
      <xs:element name="ContactTelephone" type="xs:string" minOccurs="0"  maxOccurs="1"/>
      <xs:element name="ContactFax" type="xs:string" minOccurs="0"  maxOccurs="1"/>
      <xs:element name="ContactEmail" type="xs:string" minOccurs="0"  maxOccurs="1"/>
      <xs:element ref="MainApplicant"  maxOccurs="1"/>
      <xs:element ref="JointApplicant" minOccurs="0" maxOccurs="1"/>
      <xs:element ref="Asset" minOccurs="0" maxOccurs="1"/>
    </xs:any>


</xs:complexType>

I need something a bit like this... (I wish it were this simple but alas not..)

<xs:complexType>
  <xs:choice>

    <xs:any>
      <xs:element name="UserID" type="xs:string" minOccurs="1"/>
      <xs:element name="Password" type="xs:string" minOccurs="1"/>
      <xs:element name="ReferenceNumber" type="xs:string" minOccurs="0"  maxOccurs="1"/>
      <xs:element name="CustomerId" minOccurs="1" maxOccurs="1">
        <xs:simpleType>
          <xs:restriction base="xs:integer">
            <xs:minInclusive value="0"/>
            <xs:maxInclusive value="0"/>
          </xs:restriction>
        </xs:simpleType>
      </xs:element>
      <xs:element ref="WhereSigned"/>
      <xs:element name="ContactName" type="xs:string" minOccurs="0"  maxOccurs="1"/>
      <xs:element name="ContactTelephone" type="xs:string" minOccurs="0"  maxOccurs="1"/>
      <xs:element name="ContactFax" type="xs:string" minOccurs="0"  maxOccurs="1"/>
      <xs:element name="ContactEmail" type="xs:string" minOccurs="0"  maxOccurs="1"/>
      <xs:element ref="MainApplicant"  maxOccurs="1"/>
      <xs:element ref="JointApplicant" minOccurs="0" maxOccurs="1"/>
      <xs:element ref="Asset" minOccurs="0" maxOccurs="1"/>
    </xs:any>

    <xs:any>
      <xs:element name="UserID" type="xs:string" minOccurs="1"/>
      <xs:element name="Password" type="xs:string" minOccurs="1"/>
      <xs:element name="ReferenceNumber" type="xs:string" minOccurs="0"  maxOccurs="1"/>
      <xs:element name="CustomerId" minOccurs="1" maxOccurs="1">
        <xs:simpleType>
          <xs:restriction base="xs:integer">
            <xs:minInclusive value="1"/>
          </xs:restriction>
        </xs:simpleType>
      </xs:element>
      <xs:element ref="Asset" minOccurs="0" maxOccurs="1"/>
    </xs:any>

   </xs:choice>
</xs:complexType>

Any XSD experts (do these even exist?!) who are able to lend a hand or some advice?

like image 522
Shawson Avatar asked Nov 03 '15 16:11

Shawson


People also ask

How do you make an element required in XSD?

The "use" property in the XSD definition is used to specify if the attribute is optional or mandatory. To specify that an attribute must be present, use="required" (Note: use may also be set to "prohibited", but we'll come to that later).

Which element is used to indicate that elements defined in the XSD?

The sequence element specifies that the child elements must appear in a sequence. Each child element can occur from 0 to any number of times.

How do you assert in XSD?

XSD 1.1 allows assertions on simple types to be defined. The mechanism is to define an xs:assertion element as a child of the xs:restriction child of the xs:simpleType element (that is, it acts as an additional facet). The type must be an atomic type. The value of the test attribute of xs:assert is an XPath expression.

What is complexType and simpleType in XSD?

XSD elements can be of type simpleType , complexType , or anyType . An element of type simpleType contains only text. It cannot have attributes and elements. An element of type complexType can contain text, elements, and attributes.


1 Answers

This is possible in XSD 1.1; below is a simplified example, which assumes MainApplicant and WhereSigned are mandatory when CustomerId is equal to zero.

<?xml version="1.0" encoding="utf-8" ?>
<!-- XML Schema generated by QTAssistant/XSD Module (http://www.paschidev.com) -->
<xsd:schema elementFormDefault="qualified" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xtm="http://paschidev.com/schemas/metadata/xtm">
    <xsd:complexType name="Request">
        <xsd:all>
            <xsd:element name="UserID" type="xsd:string" />
            <xsd:element name="Password" type="xsd:string" />
            <xsd:element name="ReferenceNumber" type="xsd:string" minOccurs="0"/>
            <xsd:element name="CustomerId" type="xsd:integer"/>
            <xsd:element ref="WhereSigned" minOccurs="0"/>
            <xsd:element name="ContactName" type="xsd:string" minOccurs="0" />
            <xsd:element name="ContactTelephone" type="xsd:string" minOccurs="0" />
            <xsd:element name="ContactFax" type="xsd:string" minOccurs="0" />
            <xsd:element name="ContactEmail" type="xsd:string" minOccurs="0" />
            <xsd:element ref="MainApplicant" minOccurs="0" />
            <xsd:element ref="JointApplicant" minOccurs="0" />
            <xsd:element ref="Asset" minOccurs="0" />
        </xsd:all>
        <xsd:assert test="CustomerId[. eq 0] and WhereSigned and MainApplicant or CustomerId[. ne 0]" />
    </xsd:complexType>
    <xsd:element name="Asset"/>
    <xsd:element name="MainApplicant" />
    <xsd:element name="JointApplicant" />
    <xsd:element name="WhereSigned" />  
</xsd:schema>

Minimum valid XML, when CustomerId is zero:

<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="Request">
    <UserID>UserID1</UserID>
    <Password>asodasqZX==</Password>
    <CustomerId>0</CustomerId>
    <WhereSigned/>
    <MainApplicant/>
</root>

When CustomerId is non-zero, then this is the minimum XML:

<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="Request">
    <UserID>UserID1</UserID>
    <Password>asodasqZX==</Password>
    <CustomerId>1</CustomerId>
</root>

The conditional can be easily controlled (see the @test expression); add regular XSD constraints as needed (e.g. if your CustomerId needs to be greater than or equal to zero, then make it nonNegativeInteger, etc.)

like image 176
Petru Gardea Avatar answered Sep 28 '22 04:09

Petru Gardea