How to specify in an XML schema that either one of two fields must be present? - xsd

I want to specify that either fieldname or freetext must always be present in XML files that apply to this XSD. Is there a way to do that?
<xs:complexType name="tSome">
<xs:sequence>
<!-- either one of the two below has to be present. -->
<xs:element name="fieldname" type="xs:string" />
<xs:element name="freetext" type="xs:string" />
<!-- this one below must always be present -->
<xs:element name="dbtablename" type="xs:string" />
</xs:sequence>
</xs:complexType>

There is a Choice Indicator in XML Schema, which allows you to take one of the contained elements, but not two or more. If you want any 2 of 3, I suggest doing something like this:
<xs:choice>
<xs:element name="fieldname" type="xs:string" minOccurs="0" maxOccurs="1" />
<xs:element name="freetext" type="xs:string" minOccurs="0" maxOccurs="1" />
<xs:element name="dbtablename" type="xs:string" minOccurs="0" maxOccurs="1" />
</xs:choice>
<xs:choice>
<xs:element name="fieldname" type="xs:string" minOccurs="0" maxOccurs="1" />
<xs:element name="freetext" type="xs:string" minOccurs="0" maxOccurs="1" />
<xs:element name="dbtablename" type="xs:string" minOccurs="0" maxOccurs="1" />
</xs:choice>
(Maybe maxOccurs will prevent you from choosing one and the same element twice.)
If that does not work, nothing will I think.
Edited: I didn't correctly understand the question the first time. If you want dbtablename to always be present with any one of fieldname or freetext, then this is the answer:
<xs:complexType name="tSome">
<xs:sequence>
<xs:choice>
<xs:element name="fieldname" type="xs:string" />
<xs:element name="freetext" type="xs:string" />
</xs:choice>
<xs:element name="dbtablename" type="xs:string" />
</xs:sequence>
</xs:complexType>

So, you want either fieldname or freetext and not both? or maybe both? and then dbtablename optionally?
Here is 1 or 2 of the elements:
<xs:choice minOccurs="1" maxOccurs="2">
<xs:element name="fieldname" type="xs:string"/>
<xs:element name="freetext" type="xs:string"/>
<xs:element name="dbtablename" type="xs:string"/>
</xs:choice>
Is this what you want? or did you want dbtablename to be separate?

Related

I need one element in xs:all to repeat twice

<xs:complexType>
<xs:all>
<xs:element name="AN" minOccurs="0"/>
<xs:element name="ME" minOccurs="0"/>
<xs:element name="preview" minOccurs="0"/>
<xs:element name="NZ" minOccurs="0"/>
<xs:element name="RE" minOccurs="0"/>
<xs:element name="RU" minOccurs="0"/>
<xs:element name="AU" minOccurs="0"/>
<xs:element name="SE" minOccurs="0"/>
<xs:element name="CM" minOccurs="0"/>
</xs:all>
</xs:complexType>
</xs:element>
In the above code, i want the element "ME" to be used twice in XML and other elements should be used exactly once but in anyorder.
What you want to do is the following. However while this is fine under XSD 1.1, its not under XSD 1.0.
<xs:element name="MyElm">
<xs:complexType>
<xs:all>
<xs:element name="AN" />
<xs:element name="ME" minOccurs="2" maxOccurs="2" />
<xs:element name="preview" />
<xs:element name="NZ" />
<xs:element name="RE" />
<xs:element name="RU" />
<xs:element name="AU" />
<xs:element name="SE" />
<xs:element name="CM" />
</xs:all>
</xs:complexType>
</xs:element>
In XSD 1.0, I'm pretty sure this is not possible. If you can live without them being 'in any order' then you can use a xs:sequence, and if you can live with 0-1 and 0-2 items then you could use a xs:choice. But that's as close as you can get.

Change minimum restriction of a type within a complex type

I have a complex type called SafetyTiming and it has 2 elements value and margin. Both value and margin are based on a simpletype called Timing.
<xs:simpleType name="Timing">
<xs:restriction base="xs:unsignedInt">
<xs:minInclusive value="0" />
<xs:maxInclusive value="999" />
</xs:restriction>
</xs:simpleType>
<xs:complexType name="SafetyTiming">
<xs:sequence>
<xs:element name="Value" type="Timing" minOccurs="1" maxOccurs="1" />
<xs:element name="Margin" type="Timing" minOccurs="1" maxOccurs="1" />
</xs:sequence>
</xs:complexType>
<xs:element name="SafetyTimings">
<xs:complexType>
<xs:all>
<xs:element name="A" type="SafetyTiming" minOccurs="1" maxOccurs="1" />
<xs:element name="B" type="SafetyTiming" minOccurs="1" maxOccurs="1" />
<xs:element name="C" type="SafetyTiming" minOccurs="1" maxOccurs="1" />
<xs:element name="D" type="SafetyTiming" minOccurs="1" maxOccurs="1" />
</xs:all>
</xs:complexType>
</xs:element>
This was fine until I found out that elements A and B need to have a minimum of 0 for simpletype "value" and, C and D a minimum of 1.
How can I elegantly solve this?
I tried the following but I think it looks rather messy and I wonder if there is a better solution.
<!--Safety timing type containing the timing value (minimum 0) and the value margin-->
<xs:complexType name="SafetyTiming_min0">
<xs:sequence>
<xs:element name="Value" type="Timing" minOccurs="1" maxOccurs="1" />
<xs:element name="Margin" type="Timing" minOccurs="1" maxOccurs="1" />
</xs:sequence>
</xs:complexType>
<!--Safety timing type containing the timing value (minimum 1) and the value margin-->
<xs:complexType name="SafetyTiming_min1">
<xs:sequence>
<xs:element name="Value" minOccurs="1" maxOccurs="1">
<xs:simpleType>
<xs:restriction base="Timing">
<xs:minInclusive value="1" />
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="Margin" type="Timing" minOccurs="1" maxOccurs="1" />
</xs:sequence>
</xs:complexType>
You can derive a restricted type from Timing:
<xs:simpleType name="CDTiming">
<xs:restriction base="Timing">
<xs:minInclusive value="1" />
</xs:restriction>
</xs:simpleType>
It's simpler to just create a new type for C and D which has the restricted Value:
<xs:complexType name="CDSafetyTiming">
<xs:sequence>
<xs:element name="Value" type="CDTiming" minOccurs="1" maxOccurs="1" />
<xs:element name="Margin" type="Timing" minOccurs="1" maxOccurs="1" />
</xs:sequence>
</xs:complexType>
You don't need to change anything for A and B since the original type already has a minimum of 0.
If you can change your original XSD, you can use the new type in the definition of your elements:
<xs:element name="SafetyTimings">
<xs:complexType>
<xs:all>
<xs:element name="A" type="SafetyTiming" minOccurs="1" maxOccurs="1" />
<xs:element name="B" type="SafetyTiming" minOccurs="1" maxOccurs="1" />
<xs:element name="C" type="CDSafetyTiming" minOccurs="1" maxOccurs="1" />
<xs:element name="D" type="CDSafetyTiming" minOccurs="1" maxOccurs="1" />
</xs:all>
</xs:complexType>
</xs:element>

How to use extension in xsd when order of element is important

I have some complexType element which is parent of some element:
<xs:complexType name="elementParent">
<xs:sequence>
<xs:element name="b" type="xs:String" />
<xs:element name="c" type="xs:String" />
</xs:complexType>
now I want to create anothex complex type which will be extension of my parent. Problem is in order. First element should be a then b and then c. I just know this option where order will be b c a which I dont want:
<xs:complexType name="elementChild">
<xs:complexContent>
<xs:extension base="elementParent">
<xs:sequence>
<xs:element name="a" type="xs:String" />
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:extension> creates a type which is a sequence containing first the base type and then the explicit content defined in <xs:extension>. If you only want to add new elements preceding the elements of another type, you could define the common elements as an <xs:group> and then refer to that group in both of the type definitions.
Something like this:
<!-- common elements defined as a group -->
<xs:group name="elementGroup">
<xs:sequence>
<xs:element name="b" type="xs:string" />
<xs:element name="c" type="xs:string" />
</xs:sequence>
</xs:group>
<!-- group is referred to in element type definitions -->
<xs:element name="elementParent">
<xs:complexType>
<xs:sequence>
<xs:group ref="elementGroup" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="elementChild">
<xs:complexType>
<xs:sequence>
<xs:element name="a" type="xs:string" />
<xs:group ref="elementGroup" />
</xs:sequence>
</xs:complexType>
</xs:element>

XSD - how to add two 'ref' to the same element

I have been trying to form this XSD, can someone help please...
I have an element 'country' as below:
<xs:element name="country">
<xs:complexType>
<xs:sequence>
<xs:element name="id" type="xs:long" minOccurs="0" />
<xs:element name="isoCode" type="xs:string" minOccurs="0" />
<xs:element name="currencyCode" type="xs:string" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
Now, I need to form XSD with two elements, 'source country' and 'destination country' which should both reference to 'country'. Can someone please help me to form that XSD.
<xs:element name="crossCountries">
<xs:complexType>
<xs:sequence>
<xs:element name="id" type="xs:long" minOccurs="0" />
<xs:element ref="country" /> <!-- Source Country -->
<xs:element ref="country" /> <!-- Destination Country -->
</xs:sequence>
</xs:complexType>
</xs:element>
You cannot reference an element and assign a different tag name to that reference. What you want to do instead is to define the content model for that element (a complex type would do) and reuse that under differently named tags.
<xs:complexType name="country">
<xs:sequence>
<xs:element name="id" type="xs:long" minOccurs="0" />
<xs:element name="isoCode" type="xs:string" minOccurs="0" />
<xs:element name="currencyCode" type="xs:string" minOccurs="0" />
</xs:sequence>
</xs:complexType>
Then:
<xs:element name="crossCountries">
<xs:complexType>
<xs:sequence>
<xs:element name="id" type="xs:long" minOccurs="0" />
<xs:element name="sourceCountry" type="country" /> <!-- Source Country -->
<xs:element name="destinationCountry" type="country" /> <!-- Destination Country -->
</xs:sequence>
</xs:complexType>
</xs:element>

XML Schema with complext type containing <xs:all> and <xs:any>?

I want to define a complex type that contains elements that may or may not exist, and also allows for additional undefined elements so I've got something like this:
<xs:complexType name="MyType">
<xs:sequence>
<xs:element name="A" type="xs:float" minOccurs="0" maxOccurs="1" />
<xs:element name="B" type="xs:float" minOccurs="0" maxOccurs="1" />
<xs:element name="C" type="xs:float" minOccurs="0" maxOccurs="1" />
<xs:any minOccurs="0" processContents="skip"/>
</xs:sequence>
</xs:complexType>
I don't want to force the order using <xs:sequence> so I want to change the <xs:sequence> to <xs:all> but then <xs:any> isn't allowed. Is there some way to accomplish this?
To allow any order, use this:
<xs:complexType name="MyType">
<xs:all minOccurs="1" maxOccurs="1">
<xs:element name="A" type="xs:float" minOccurs="0" maxOccurs="1" />
<xs:element name="B" type="xs:float" minOccurs="0" maxOccurs="1" />
<xs:element name="C" type="xs:float" minOccurs="0" maxOccurs="1" />
</xs:all>
</xs:complexType>
But then, you can't have an <any> inside an <all>.
Nor can you have them both inside one type, either directly or as an extension.

Resources