Can XSD add a constraint for comparing two elements? - xsd

Can XSD add a constraint for comparing two elements ?
Say I have Begin End under DataRangeType I want to add a constraint saying Begin <= End. Is this doable ?
BTW I am using XMLSpy 2013.
<xs:complexType name="DataRangeType">
<xs:sequence>
<xs:element name="Begin" type="xs:date"/>
<xs:element name="End" type="xs:date"/>
</xs:sequence>
</xs:complexType>
Thanks a lot.

It's doable in XSD 1.1 by means of assertions. I do not believe the constraint is expressible in XSD 1.0.
[Addendum] You ask for an example. Here you are.
<xs:complexType name="DataRangeType">
<xs:sequence>
<xs:element name="Begin" type="xs:date"/>
<xs:element name="End" type="xs:date"/>
</xs:sequence>
<xs:assert test="Begin <= End"/>
</xs:complexType>

Related

constraints on basis of tag value in xsd

I have to create constraints on below xml on basis of its tag value
<struct>
<member>
<name>Identifier</name>
<value><i4>11002</i4></value>
</member>
<member>
<name>StartDate</name>
<value><dateTime.iso8601>20160701T12:00:00+0000</dateTime.iso8601>
</value>
</member>
<member>
<name>Type</name>
<value><i4>0</i4></value>
</member>
</struct>
The xsd format that i have created is like,it is just the short form of code and generated using a tool online.
<xs:element minOccurs="0" name="struct">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="unbounded" name="member">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" name="name" type="xs:string" />
<xs:element minOccurs="0" name="value">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" name="string" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
What i need is to put constraint on startDate that it is of correct format.
and identifier is only 5 to 10 digits long.
Your XML design is excessively meta and is thereby frustrating your ability to express constraints on data values using XSD 1.0.
You can do one of the following:
Redesign your XML to use concrete tag names such as Identifier, StartDate etc.
Constrain i4 and dateTime.iso8601 apart from name.
Use XSD 1.1 assertions to enforce checking based upon the value of
name.
Recommend you choose #1.

Unique constraint on a complexType instead of an element

I have the following XSD structure:
<xs:schema xmlns:ns="http://abc/">
...
<xs:element name="abc">
<xs:complexType>
<xs:sequence>
<xs:element ref="map"/>
</xs:sequence>
</xs:complexType>
</xs:element>
...
<xs:element name="map">
<xs:complexType>
<xs:sequence>
<xs:element name="entry" type="ns:MapEntryType" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:unique name="entry">
<xs:selector xpath="entry"/>
<xs:field xpath="key"/>
</xs:unique>
</xs:element>
<xs:complexType name="MapEntryType">
<xs:sequence>
<xs:element name="key" type="xs:string"/>
<xs:element name="value" type="xs:anyType"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
This is doing its job.
The map element now has to be called something different based on whichever is the wrapper, so the name is sometimes map, sometimes properties, sometimes options, etc.
Therefore I want to genericize the map element.
I tried doing the following:
Making map a xs:complexType and changing ref to type.
This resulted in xs:unique not being accepted and failed
Making map a xs:complexType, changing ref to type and moving the xs:unique constraint to the element definitions.
This worked but resulted in the XSD having a lot of xs:unique present in the document.
Isn't there a way to simply tell that I want a specific structure and it containing unique elements without having to repeat the unique constraint everywhere?
As Petru Gardea said in his answer
Both XSD 1.0 and 1.1 place the identity constraints under an element
So you have to add xs:unique to every element, but if you are using XSD 1.1 you can define only once a complete xs:unique and then in the rest of the elements use xs:unique ref="name". This is not valid for you as you are using XSD 1.0, but I let it here for future XSD 1.1 users that find this good question.
Example (namespaces removed for clarity):
<xs:element name="map">
<xs:complexType>
<xs:sequence>
<xs:element name="entry" type="MapEntryType" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<!-- Only completely defined once -->
<xs:unique name="uniqueEntry">
<xs:selector xpath="entry"/>
<xs:field xpath="key"/>
</xs:unique>
</xs:element>
<xs:element name="hashMap">
<xs:complexType>
<xs:sequence>
<xs:element name="entry" type="MapEntryType" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<!-- Referenced here and every other time -->
<xs:unique ref="uniqueEntry"/>
</xs:element>
Short answer, it is not possible. Both XSD 1.0 and 1.1 place the identity constraints under an element; a constraint cannot be globally defined, therefore there is no "reuse" per se, other than that of the enclosing element. Given your scenario (different element names for different needs) it is not possible to reuse.

After importing a complextype in one xsd from another xsd, is it possible to have selected subelements of the complex type in the second xsd

After importing a complextype in one xsd from another xsd, is it possible to have selected subelements of the complex type in the second xsd
What I mean is :
I have first xsd. -> AddressFile.xsd .In AddressFile.xsd, there is a complex type IndividualAddress, with 5 subelemnts. In the next xsd, Individual.xsd , I am referring to the complext type IndividualAddress in AddressFile.xsd. But in Individual.xsd, I just want DoorNO , StreetNum and State from the complex Type IndividualAddress directly . Is that possible. Is there any restrictions I can use.
AddressFile.xsd
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://abc/DP/Address">
<xs:complexType name="IndividualAddress">
<xs:annotation>
<xs:documentation>Address of an individual
</xs:documentation>
</xs:annotation>
<xs:sequence>
<xs:element name="DoorNO" type="xs:String"
nillable="true" minOccurs="0"/>
<xs:element name="StreetNum" type="xs:String"
nillable="true" minOccurs="0"/>
<xs:element name="State" type="xs:String"
nillable="true" minOccurs="0"/>
<xs:element name="Country" type="xs:String"
nillable="true" minOccurs="0"/>
<xs:element name="Pin" type="xs:String"
nillable="true" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
Individual.xsd
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:address="http://abc/DP/Address"
targetNamespace="http://abc/DP/Individual">
<xs:import namespace="http://abc/DP/Address"
schemaLocation="AddressFile.xsd"/>
<xs:complexType name="Individual">
<xs:annotation>
<xs:documentation>Address of an individual
</xs:documentation>
</xs:annotation>
<xs:sequence>
<xs:element name="Name" type="xs:String"
nillable="true" minOccurs="0"/>
<xs:element name="Age" type="xs:int"
nillable="true" minOccurs="0"/>
<xs:element name="DoorNO" type=" address:IndividualAddress "
nillable="true" minOccurs="0"/>
<xs:element name="StreetNum" type=" address:IndividualAddress "
nillable="true" minOccurs="0"/>
<xs:element name="State" type=" address:IndividualAddress "
nillable="true" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
Your best approach depends on what you are trying to accomplish.
If you want XSD-aware tools to know that complex type Individual is derived from complex type IndividualAddress, you can derive the one from the other. You will need to do so in two steps: a restriction step to get rid of the unwanted child elements of the base type and then an extension step to add more elements, at the end. (Not at the beginning.)
If you just want to reuse the elements, the creator of the base schema has done the best job they can to hinder you, by making all the children of IndividualAddress local types, which cannot be referred to from elsewhere. If they wanted to make reuse easy, or even possible, they would (a) make the elements in question top-level elements, and/or possibly (b) use named model groups to package up groups of useful elements to be used together.

Restricting number of element count in <all> XSD Schema

What I'm trying to do is, declare an parent element called "data", which are having 10 sub element of these one element are conditional.
My XSD is:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning" elementFormDefault="qualified" attributeFormDefault="unqualified" vc:minVersion="1.1">
<xs:element name="data" >
<xs:complexType>
<xs:sequence>
<xs:element name="sub_data" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:all >
<xs:element ref="A"/>
<xs:element ref="B" minOccurs="0" maxOccurs="1"/>
<xs:element ref="C"/>
<xs:element ref="D"/>
<xs:element ref="E"/>
<xs:element ref="F"/>
<xs:element ref="G"/>
<xs:element ref="H"/>
<xs:element ref="I"/>
<xs:element ref="J"/>
<xs:element ref="K"/>
<xs:element ref="L"/>
<xs:element ref="M"/>
<xs:element ref="N"/>
<xs:element ref="element_group"/>
</xs:all>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="status"/>
</xs:complexType>
</xs:element>
<xs:element name="O" type="xs:string" substitutionGroup="element_group">
<xs:element name="P" type="xs:string" substitutionGroup="element_group">
<xs:element name="Q" type="xs:string" substitutionGroup="element_group">
</xs:schema>
Requirement is:
All element from A to N are appearing in any order.
Element P,Q and R is also part of data but only one element appear from among 3. Order is also any.
More important I have cover 1st and 2nd point but I want one more restriction is that only and only four element will be become the part of <data> that means element count from <A> to <Q> is exact four,
Combination can any of them from <A> to <Q> but final count is only four, please help me.
Now currently i am unable to set maxOccures in <all> , it not compiling the xsd after setting maxOccures.
The simplest way to handle this is probably to use XSD 1.1 and use an assertion on the parent to specify that there must be exactly (or at most) four children. You will also need to make each child of the all-group optional, since thirteen of them will not appear.
The best way might be to redesign your XML to work better with your schema language instead of fighting it. It's hard to give advice on that, though, since your example is abstract enough to make it unclear why you are imposing the requirements you mention.

Is it possible to have multiple names for a single complex type defined in a XSD?

I am creating an XSD where I defined a complex type:
<xs:complexType name="TimeBasicComponents">
<xs:sequence>
<xs:element name="Hours" type="xs:int"></xs:element>
<xs:element name="Minutes" type="xs:int"></xs:element>
<xs:element name="Seconds" type="xs:int"></xs:element>
<xs:element name="MilliSeconds" type="xs:int"></xs:element>
</xs:sequence>
</xs:complexType>
I defined another complex type:
<xs:complexType name="TimeOfDay">
<xs:sequence>
<xs:element name="BasicComponents" type="TimeBasicComponents"></xs:element>
<xs:element name="Zone" type="xs:string"></xs:element>
</xs:sequence>
</xs:complexType>
Now, I want to have another complex type for time duration. However, there is actually no need to define another complex type for this, it will be exactly same as "TimeBasicComponents". So, I was wondering if there is way to define multiple names for a single complex type in XSD?
-Sandeep
Are you saying that you want to use TimeBasicComponents as a duration also? To my knowledge you can't have alias'es for a complexType but you can achieve something very similar using the <xs:extension... construct:
<xs:complexType name="TimeDuration">
<xs:complexContent>
<xs:extension base="TimeBasicComponents" />
</xs:complexContent>
</xs:complexType>
That way you will effectively have an alias without having to redefine the TimeBasicComponents complex-type.
Cheers,

Resources