Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

xsd property set required according to enum value

I have following xsd for my project I am trying to make single xsd for both xmls ACH and CC on basis of Payment Method enum attribute if payment method is Ach then ACHInfo becomes required else CreditCardInfo..

<xs:element name="PaymentMethod">
  <xs:simpleType>
    <xs:restriction base="xs:string">
      <xs:enumeration value="ACH"/>
      <xs:enumeration value="CreditCard"/>
    </xs:restriction>
  </xs:simpleType>
</xs:element>
<xs:element name="CreditCardInfo" minOccurs="0">
  <xs:complexType>
    <xs:all>
      <xs:element name="Cvv2No">
        <xs:simpleType>
          <xs:restriction base="xs:string">
            <xs:maxLength value="4"/>
          </xs:restriction>
        </xs:simpleType>
      </xs:element>
      <xs:element name="CardNumber">
        <xs:simpleType>
          <xs:restriction base="xs:string">
            <xs:maxLength value="20"/>
          </xs:restriction>
        </xs:simpleType>
      </xs:element>
     </xs:all>
  </xs:complexType>
</xs:element>
<xs:element name="ACHInfo" minOccurs="0">
  <xs:complexType>
    <xs:all>
      <xs:element name="RoutingNumber" nillable="false">
        <xs:simpleType>
          <xs:restriction base="xs:string">
            <xs:maxLength value="50"/>
          </xs:restriction>
        </xs:simpleType>
      </xs:element>
      <xs:element name="AccountNumber" nillable="false">
        <xs:simpleType>
          <xs:restriction base="xs:string">
            <xs:maxLength value="50"/>
          </xs:restriction>
        </xs:simpleType>
      </xs:element>
    </xs:all>
  </xs:complexType>
</xs:element>

can any one give me solution for this what changes required in xsd to make property required according to enum value.

Thanks.

like image 331
Muhammad Mansoor Avatar asked May 28 '13 08:05

Muhammad Mansoor


People also ask

What is enumeration value in XSD?

Enumerations are a base simple type in the XSD specification containing a list of possible values. Single-valued enumerations are shown as restrictions of the base simple type xs:token , as illustrated below: ? < xs:simpleType name=”GraduationPlanTypeMapType”>

How do I restrict attribute values in XML schema?

Restrictions on a Set of Values To limit the content of an XML element to a set of acceptable values, we would use the enumeration constraint. Note: In this case the type "carType" can be used by other elements because it is not a part of the "car" element.

What is restriction in XSD?

restriction. restriction is normally a range of conditions to be applied on the element's value. In this example, we've set a restriction on marks that marks should be in range of 0 to 100 with both values are included. <xs:minInclusive value = "0"/> <xs:maxInclusive value = "100"/>

How can an element be defined within an XSD?

Each element definition within the XSD must have a 'name' property, which is the tag name that will appear in the XML document. The 'type' property provides the description of what type of data can be contained within the element when it appears in the XML document.


1 Answers

Four solutions, some of which involve re-thinking the XML representation of your information:

XSD 1.1 assertion

The easiest way to do just what you describe is to use XSD 1.1 and define the constraint you have in mind with an assertion. You don't say what the parent element is called; I'll call it Payment. And I'll use the prefix tns for the target namespace.

<xs:element name="Payment">
  <xs:complexType>
    <xs:sequence>
      <xs:element ref="tns:PaymentMethod"/>
      <xs:choice>
        <xs:element ref="tns:ACHInfo" minOccurs="0"/>
        <xs:element ref="tns:CreditCardInfo" minOccurs="0"/>
      </xs:choice>
    </xs:sequence>
    <xs:assert test="(tns:PaymentType = 'ACH' and ./tns:ACHInfo)
                     or
                     (tns:PaymentType = 'CreditCard' 
                       and ./tns:CreditCardInfo)"/>
  </xs:complexType>
</xs:element>

XSD 1.1 conditional type assignment

A better way, for some purposes, would be to use conditional type assignment (also a 1.1 feature) for Payment. For technical reasons, that entails making PaymentType an attribute on Payment, not a child:

<xs:element name="Payment">
  <xs:alternative test="@PaymentMethod='ACH'" 
                  type="tns:ACHPayment"/>
  <xs:alternative test="@PaymentMethod='CreditCard'" 
                  type="tns:CCPayment"/>
  <xs:alternative type="xs:error"/>
</xs:element>

This declaration means: if the value of the PaymentMethod attribute is "ACH" then element Payment has type tns:ACHPayment (which we'll define in a moment). Otherwise if the value of PaymentMethod is "CreditCard" then the type of Payment is tns:CCPayment. Otherwise, the element is invalid.

We declare the named types ACHPayment and CCPayment as containing the appropriate children (and also providing for the PaymentMethod attribute) -- we could inline them, but naming them make the conditional type assignment pattern easier to see:

<xs:complexType name="ACHPayment">
  <xs:sequence>
    <xs:element ref="tns:ACHPayment"/>
  </xs:sequence>
  <xs:attribute name="PaymentMethod" type="tns:PaymentMethod"/>
</xs:complexType>

<xs:complexType name="CCPayment">
  <xs:sequence>
    <xs:element ref="tns:CreditCardPayment"/>
  </xs:sequence>
  <xs:attribute name="PaymentMethod" type="tns:PaymentMethod"/>
</xs:complexType>

And for the same reason, we provide a named declaration for the type of the PaymentMethod attribute:

<xs:simpleType name="PaymentMethod">
  <xs:restriction base="xs:string">
    <xs:enumeration value="ACH"/>
    <xs:enumeration value="CreditCard"/>
  </xs:restriction>
</xs:simpleType>

XSD 1.0, moving payment method into the content model

But you don't need XSD 1.1 to make XML that works for your application; you just need to think differently about your design. It's easy to make ACHinfo required for ACH payments and CreditCardInfo required for credit-card payments, if you carry the choice of payment type in the name of an element instead of in content. Instead of defining the parent type as:

<xs:complexType>
  <xs:sequence>
    <xs:element ref="tns:PaymentMethod"/>
    <xs:element ref="CreditCardInfo" minOccurs="0"/>
    <xs:element ref="ACHInfo" minOccurs="0"/>
  </xs:sequence>
</xs:complexType>

you could declare it this way:

<xs:complexType>
  <xs:choice>
    <xs:sequence>
      <xs:element ref="tns:ACHPayment"/>
      <xs:element ref="tns:ACHInfo" minOccurs="0"/>
    </xs:sequence>
    <xs:sequence>
      <xs:element ref="tns:CCPayment"/>
      <xs:element ref="tns:CreditCardInfo" minOccurs="0"/>
    </xs:sequence>       
  </xs:choice>
</xs:complexType>

The two flag elements CCPayment and ACHPayment can be empty elements:

<xs:complexType name="EMPTY">
  <xs:sequence/>
</xs:complexType>

<xs:element name='ACHPayment' type="tns:EMPTY"/>
<xs:element name='CCPayment' type="tns:EMPTY"/>

But as things stand neither of these is doing any work in the design.

XSD 1.0, simplification

If neither the ACHPayment nor the CCPayment element is doing any work beyond (a) signaling that the payment uses this method of that, and (b) ensuring that the following sibling is the correct one, then neither of them is doing any work at all.

You could just as easily define the parent element this way:

<xs:element name="Payment">
  <xs:complexType>
    <xs:choice>
      <xs:element ref="tns:ACHInfo" minOccurs="0"/>
      <xs:element ref="tns:CreditCardInfo" minOccurs="0"/>
    </xs:choice>
  </xs:complexType>
</xs:element>

You can still see whether the payment is an ACH payment (the Payment element's child is named ACHInfo) or a credit-card payment (the child is named CreditCardInfo), and you no longer have to check to make sure the detail information is consistent with the PaymentMethod flag, because the PaymentMethod flag has gone away.

Fewer moving parts, less to do, less to go wrong.

Of these four designs, I think this fourth one is probably the best. Your mileage, of course, may vary.

like image 65
C. M. Sperberg-McQueen Avatar answered Dec 28 '22 07:12

C. M. Sperberg-McQueen