xsd property set required according to enum value - xsd

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.

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.

Related

XSD : how to restrict attribute inherited from base type

Consider the following xsd. For AddressType, Line1 can be any string. I want to restrict Line1 attribute in USAddressType to follow some regular expression. How can I do this ? Thanks !
<xs:complexType name="AddressType">
<xs:sequence>
<xs:element name="Line1" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="USAddressType">
<xs:complexContent>
<xs:extension base="AddressType">
<xs:sequence>
<xs:element name="State" type="xs:string"/>
<xs:element name="Zipcode" type="xs:string"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:element name="Line1">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:pattern value="REGEX HERE"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
Limitations of regular expressions used in XML Schemas can be found here

XSD validation error in #AnonType_Apps

When I tried to validate my XSD it gives the error
S4s-elt-invalid-content.1: The Content Of '#AnonType_Apps' Is Invalid.
Element 'sequence' Is Invalid, Misplaced, Or Occurs Too Often.
don't know what should be done
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name ="Apps">
<xs:complexType>
<xs:attribute name ="List_Type" use="required">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="new releases"/>
<xs:enumeration value="top rated"/>
<xs:enumeration value="category list"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name ="Server_IP" type="xs:string" fixed="10.144.50.55"/>
<xs:sequence>
<xs:element name ="App" minOccurs="1" maxOccurs="20">
<xs:complexType>
<xs:attribute name ="device_type" use="optinal" >
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="tablet"/>
<xs:enumeration value="phone"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name ="app_id" type="xs:string"/>
<xs:attribute name ="installed" type="xs:boolean" default="false"/>
<xs:sequence>
<xs:element name ="app_name" type="xs:string"></xs:element>
<xs:element name ="catogry" minOccurs="1" maxOccurs="3"></xs:element>
<xs:element name ="version" type="xs:string"></xs:element>
<xs:element name ="description" type="xs:string"></xs:element>
<xs:element name ="reviews" use="required">
<xs:complexType>
<xs:sequence>
<xs:element name ="review" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:all>
<xs:element name ="reviewer_name" type="xs:string"></xs:element>
<xs:element name ="review_date">
<xs:complexType>
<xs:restriction base="xs:string">
<xs:pattern value="\d{4}\-\d{2}\-\d{2}"/>
</xs:restriction>
</xs:complexType>
</xs:element>
</xs:all>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name ="review_time">
<xs:complexType>
<xs:restriction base="xs:string">
<xs:pattern value="\d{2}:\d{2}:\d{}"/>
</xs:restriction>
</xs:complexType>
</xs:element>
<xs:element name ="content" type="xs:string"></xs:element>
<xs:element name ="rating">
<xs:complexType>
<xs:restriction base="xs:float">
<xs:minInclusive value="0" />
<xs:maxInclusive value="5" />
</xs:restriction>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Within a complexType element, the content model comes first and the attribute declarations come last. Move the outermost sequence element to make it the first child of the complex type.
You might want to try finding a syntax-aware editor in which to edit schema documents, to alert you to problems of this kind.
Other syntactic issues in this fragment:
Other complexType elements have the same syntax error of putting their attribute declarations first.
If you want the type of rating to be a restriction of xs:float, then you want it to have a simple type, not a complex type.
Ditto for review_time and review_date.
The pattern on the type of review_time is not a legal regular expression: braces may contain information on the minimum and/or maximum occurrences of (strings matching) a subexpression, in a variety of forms, but they must contain something, so \d{} is not a legal expression. Drop the empty braces, or make it \d{1} if you like, or make it say what you want.
The xs:element element has no attribute named use; I think you may mean to say <xs:element name="reviews" minOccurs="1" maxOccurs="1"> ...
The use attribute does not accept the value optinal.
Get an editor!
Your xs:sequence element needs to follow immidiately on the complexType element.
Your review_date and review_time elements should be a simpleType with a restriction.
If you fix those issues your xsd seems validd.

xml element enumerated attribute and enumerated value in xsd

Of interest is the following xml child element:
<optInItem type='MARKETING_EMAILS'>NO</optInItem>
I'd like to enumerate possible values (assume 2 possible values) for attribute 'type' and enumerate possible values for the text value of optInItem (values could be Yes | No). I am starting with the following xsd but am not sure how to add in the two separate enumerations.
<xs:element name="optInItem" maxOccurs="2" minOccurs="2">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:string" name="type" use="required"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
Any suggestions/pointers would be appreciated.
thanks
After many iterations, it looks like the following does the trick:
<xs:element name="account">
<xs:complexType>
<xs:sequence>
<xs:element type="optInItemType" name="optInItem" maxOccurs="2" minOccurs="2">
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="optInItemType">
<xs:simpleContent>
<xs:extension base="elementOptInItemType">
<xs:attribute name="type" type="attrOptInItemType"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<xs:simpleType name="elementOptInItemType">
<xs:restriction base="xs:string">
<xs:enumeration value="YES"/>
<xs:enumeration value="NO"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="attrOptInItemType">
<xs:restriction base="xs:string">
<xs:enumeration value="MARKETING_EMAILS"/>
<xs:enumeration value="UPDATE_NOTIFICATIONS"/>
</xs:restriction>
</xs:simpleType>
That was a more complicated than I thought it would be. The simpleContent
extension base allowed a user defined type and thus was the key to pulling it
all together.

Element-Mandatory Attribute declaration in XSD Schema:

I want to declare an element to be included in a complex type declaration, and the element has a mandatory attribute: "option=MyOption", but the value of the "option" attribute could be anything, depending on the context.
That is: the attribute "option" with some unknown value should be mandatory in any document using the complex type containing this element.
Example:
<xs:element name="SpecialOption" type="xs:string"/>
<xs:complexType name="SpecialOptions">
<xs:sequence>
<xs:element ref="SpecialOption" minOccurs="1" maxOccurs="100"/>
<xs:element ref="XXX"/>
</xs:sequence>
</xs:complexType>
In this case the "SpecialOption" element in the complex type "SpecialOptions" should have this mandatory attribute.
I don't know how to declare a mandatory attribute for an element in XSD, or how to specify that the attribute must have a value that is not yet known.
You need to modify the definition of the "SpecialOption" element to include the required attribute. Update this code:
<xs:element name="SpecialOption" type="xs:string"/>
to this:
<xs:element name="SpecialOption">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="Option" type="xs:string" use="required"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
With this change your complex type will contain the required "Option" attribute on all instances of the "SpecialOption" element in the "SpecialOptions" complex type. Declaring the "Option" attribute to be of type xs:string will allow any value to be passed in this field.
1) This is a simple required string attribute
<xs:element name="SpecialOption">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="Option" type="xs:string" use="required"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
2) To require exactly one of a list of allowed values:
<xs:element name="SpecialOption">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="Option" use="required">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="DE"/>
<xs:enumeration value="EN"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
3) One can use a range as a restriction, like in the example below.
<xs:element name="SpecialOption">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="Option" use="required">
<xs:simpleType>
<xs:restriction base="xs:integer">
<xs:minInclusive value="95"/>
<xs:maxInclusive value="137"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
4) Below, the attribute is declared as a list containing decimal values. This allows an attribute to contain a subset of the specified values, e.g. Option="6 77 95".
<xs:simpleType name="Items">
<xs:restriction base="xs:decimal">
<xs:enumeration value="137"/>
<xs:enumeration value="95"/>
<xs:enumeration value="6"/>
<xs:enumeration value="77"/>
</xs:restriction>
</xs:simpleType>
<xs:element name="SpecialOption">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="Option" use="required">
<xs:simpleType>
<xs:list itemType="Items"/>
</xs:simpleType>
</xs:attribute>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
5) Here the attribute is declared optional, but provided with a default value ("test"), which is sometimes sufficient:
<xs:element name="SpecialOption">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="Option" type="xs:string" use="optional" default="test"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
To mark an attribute as mandatory you use <xs:attribute use="required" />.
As for type, you have a choice of the built-in XSD types (xs:string etc), or you can define your own <xs:simpleType /> and use that.
UPDATE
I am not certain what you mean by the attribute must have a value that is not yet known. Does this mean that the value is a string, but can be any string? Or a decimal?
Because it's an attribute value we are talking about you are restricted to using the built-in XSD types, or defining your own xs:simpleType type based on one of the built-in types. This is where you can apply more stringent rules to the allowed value, for example by extending xs:string and adding a regular expression constraint to allowed values.
<xsd:simpleType name="UKDate">
<xsd:restriction base="xsd:string">
<xsd:pattern value="(0?[1-9]|[12][0-9]|3[01])[- /.](0?[1-9]|1[012])[- /.](19|20)\d\d"/>
</xsd:restriction>
</xsd:simpleType>
However, if there is absolutely no way of knowing what value will be used then you have the well known temporal paradox whereby you cannot restrict something at design-time to a value you only know at run-time. In this instance, surely it is only necessary to specify that the attribute must at least be present?
<xs:attribute use="required" />
Hope this answers your question a little more clearly.
Simply you can do it as the following
<xs:element name="SpecialOption">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:whiteSpace value="replace"/>
<xs:minLength value="1"></xs:minLength>
</xs:restriction>
</xs:simpleType>
</xs:element>
by this code you enforce to insert a value on the xml tag and also the white space restriction will handle to remove the white space from the xml tag.

XML Schema - I need to make sure I have 2 instances of an element, one with each attribute

I need to make sure I have 2 instances of an element, one with each attribute.
Essentially I need both:
/*:SalesPersonParty/*:PartyID[#schemeAgencyName="SalesPersonID"]
AND
/*:SalesPersonParty/*:PartyID[#schemeAgencyName="SalesPersonPduID"]
I have cardinality 2..2 but 2 instances of either attribute is valid. I need one of each and order doesn't matter.
Here are the relevant schema components:
<xs:simpleType name="RestrictedString">
<xs:restriction base="xs:string">
<xs:pattern value="([0-9]{3})|([0-9]{10})" />
</xs:restriction>
</xs:simpleType>
<xs:element name="SalesPersonParty" minOccurs="2" maxOccurs="2">
<xs:complexType>
<xs:sequence>
<xs:element name="PartyID" minOccurs="1" maxOccurs="1">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="star:RestrictedString">
<xs:attribute name="schemeAgencyName" use="required">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="SalesPersonID" />
<xs:enumeration value="SalesPersonPduID" />
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
Is this even possible?
Thanks and regards,
Tony
I think you can do it with a uniqueness constraint. You'll have to know the container element for SalesPersonParty element; call it Transaction. Then you need something like:
<xs:element name="Transaction">
...
<xs:unique name="uniqueAgencyNameConstraint">
<xs:selector xpath="SalesPersonParty/PartyID">
<xs:field xpath="#schemeAgencyName"/>
</xs:unique>
</xs:element>
This says that each SalesPersonParty/PartyID must have a unique schemeAgencyName. Combined with the constraints of having exactly two SalesPersonParty elements and only two possible values in the enumeration, all values must occur once.

Resources