restriction of elements based on another attribute using XSD 1.1 - xsd

I am trying to create a schema definition using XSD 1.1 in which the number of other elements is dependent on the attribute of another element.
E.g. The number of the BaPath elements BaPath depends on the value of the attribute "service" of the "Conn" element.
The xsd I wrote is
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="Mapping">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="Link" minOccurs="0" maxOccurs="unbounded" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="Env">
<xsd:complexType>
<xsd:attribute name="name" use="required">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:enumeration value="UTEST" />
<xsd:enumeration value="TEST" />
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
<xsd:element name="Link">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="Conn" maxOccurs="unbounded" />
</xsd:sequence>
<xsd:attribute name="service" use="required">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:enumeration value="FILESNF" />
<xsd:enumeration value="MSGSNF" />
<xsd:enumeration value="MSGRT" />
<xsd:enumeration value="FILERT" />
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
<xsd:element name="Conn">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="BaPath" maxOccurs="unbounded" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="BaPath">
<xsd:complexType>
<xsd:attribute name="flow" use="required">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:assertion test="#service eq 'MSGRT'">
<xsd:enumeration value="TRS" />
<xsd:enumeration value="ZTRS" />
</xsd:assertion>
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
<xsd:element name="Dep">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="Env" maxOccurs="unbounded" />
<xsd:element ref="Mapping" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:complexType name="CfgType">
<xsd:sequence>
<xsd:element ref="Dep" />
</xsd:sequence>
</xsd:complexType>
<xsd:element name="Cfg" type="CfgType"></xsd:element>
</xsd:schema>
</Cfg>
for example if Conn element has an attribute service eq 'MSGRT' there must be 2 BaPath elements with attributes TRS and ZTRS
<Cfg xmlns="http://www.alpha.com/beta">
<Dep>
<Env name="UTEST"/>
<Mapping>
<Link t2s_service="MSGRT">
<Conn>
<BaPath flow="ZTRS"/>
<BaPath flow="TRS"/>
</Conn>
</Link>
</Mapping>
</Dep>
if service eq 'FILESNF' of Conn there must 3 BaPath elements with attributes FTS, ZFTS and MSSDN
I tried different solutions but no one seems to work. Is it possbile to solve this problem with assertion of xsd-1.1?

You could use asserts in the Link element (and a enumeration with all the values in the flow attribute).
<xsd:element name="Link">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="Conn" maxOccurs="unbounded"/>
</xsd:sequence>
<xsd:attribute name="service" use="required">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:enumeration value="FILESNF"/>
<xsd:enumeration value="MSGSNF"/>
<xsd:enumeration value="MSGRT"/>
<xsd:enumeration value="FILERT"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>
<xsd:assert test="(#service ne 'MSGRT') or (count(Conn[count(BaPath[#flow eq 'TRS']) eq 1 and count(BaPath[#flow eq 'ZTRS']) eq 1 and count(BaPath) eq 2]) eq count(Conn))"></xsd:assert>
<xsd:assert test="(#service ne 'FILESNF') or (count(Conn[count(BaPath[#flow eq 'FTS']) eq 1 and count(BaPath[#flow eq 'MSSDN']) eq 1 and count(BaPath[#flow eq 'ZFTS']) eq 1 and count(BaPath) eq 3]) eq count(Conn))"></xsd:assert>
</xsd:complexType>
</xsd:element>
Explanation of one of the assert (the other asserts would be similar):
(#service ne 'MSGRT') or (count(Conn[count(BaPath[#flow eq 'TRS']) eq 1 and count(BaPath[#flow eq 'ZTRS']) eq 1 and count(BaPath) eq 2]) eq count(Conn))
First we check the service attribute.
Then, using Conn[count(BaPath[#flow eq 'TRS']) eq 1 and count(BaPath[#flow eq 'ZTRS']) eq 1 and count(BaPath) eq 2] we are selecting all the Conn element of the Link that have exactly two BaPath childs (one with flow=TRS and other with flow=ZTRS).
After that we check that all of the Conn elements pass that restriction.
So, using that, this example will be valid:
<Link service="MSGRT">
<Conn>
<BaPath flow="TRS"></BaPath>
<BaPath flow="ZTRS"></BaPath>
</Conn>
</Link>
This example will not be valid:
<Link service="MSGRT">
<Conn>
<BaPath flow="MSSDN"></BaPath>
<BaPath flow="ZTRS"></BaPath>
</Conn>
</Link>
This example will not be valid:
<Link service="MSGRT">
<Conn>
<BaPath flow="TRS"></BaPath>
</Conn>
</Link>
This example will not be valid:
<Link service="MSGRT">
<Conn>
<BaPath flow="TRS"></BaPath>
<BaPath flow="ZTRS"></BaPath>
<BaPath flow="ZFTS"></BaPath>
</Conn>
</Link>
Edit:
Another option it's to use conditional type alternatives (example here), but you would probably need to duplicate parts of your Schema.

Related

UML aggregation/association to XML Schema

long story short:
I want to genererate XSD from UML for this I need a way to represent UML aggregation/association in XSD. I found a mapping an they recommend (for aggregation/association) : "reference element with IDREF attribute and referencing the associated class and keyref for type saftey (key/keyref reference)". But I dont know how to do this exactly because I'm really new in XSD ( < 1 week).
So this is what I thought it should look like but im not sure^^ Does anybody has some advices or can correct if my code has errors?
uml: http://i39.tinypic.com/15x8ufp.png
<xsd:schema elementFormDefault="qualified" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ns="namespace" targetNamespace="namespaceURI">
<xsd:import namespace="namespace" />
<xsd:element name="root">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="classA">
<xsd:complexType>
<xsd:all>
<xsd:element name="attributeElement" />
</xsd:all>
<xsd:attribute name="aId" type="xsd:ID" use="required" />
</xsd:complexType>
<xsd:key name="classAKey">
<xsd:selector xpath="ns:root/ns:classA" />
<xsd:field xpath="#aId" />
</xsd:key>
</xsd:element>
<xsd:element name="classB">
<xsd:complexType>
<xsd:all>
<xsd:element name="refClassA" minOccurs="0" maxOccurs="unbounded"/>
</xsd:all>
<xsd:attribute name="bId" type="xsd:ID" use="required" />
</xsd:complexType>
<xsd:key name="classBKey">
<xsd:selector xpath="ns:root/ns:classB" />
<xsd:field xpath="#bId" />
</xsd:key>
<xsd:keyref name="classARef" refer="ns:classAKey">
<xsd:selector xpath="ns:classB" />
<xsd:field xpath="./refClassA" />
</xsd:keyref>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
Perhaps UML For W3C XML Schema Design will help answer your questions. It is old, but the basics of what it shows still apply today and is pretty clearly presented.

Limit value of element to value in other element XSD

Given the following type:
<xsd:complexType name="Options">
<xsd:sequence>
<xsd:element name="option" maxOccurs="unbounded">
<xsd:complexType>
<xsd:all>
<xsd:element name="id" type="xsd:integer" />
<xsd:element name="label" type="xsd:string" />
<xsd:element name="value" type="xsd:string" minOccurs="0" />
<xsd:element name="dependency" type="xsd:integer" minOccurs="0" />
</xsd:all>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
How can I express that a dependency of one option must exist as an id of a different option?
I think I'm supposed to be using xsd:key and xsd:keyref, but having trouble understanding how to use them.
XSD 1.0 doesn't support this. XSD 1.1 supports Conditional Types and assertions which might allow you to do this. For xsd 1.0 you can use Schematron to achieve this.
Constraints can only be expressed in the context of an element.
<?xml version="1.0" encoding="utf-8" ?>
<!--XML Schema generated by QTAssistant/XML Schema Refactoring (XSR) Module (http://www.paschidev.com)-->
<xsd:schema elementFormDefault="qualified" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:complexType name="Options">
<xsd:sequence>
<xsd:element name="option" maxOccurs="unbounded">
<xsd:complexType>
<xsd:all>
<xsd:element name="id" type="xsd:integer"/>
<xsd:element name="label" type="xsd:string"/>
<xsd:element name="value" type="xsd:string" minOccurs="0"/>
<xsd:element name="dependency" type="xsd:integer" minOccurs="0"/>
</xsd:all>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:element name="Options" type="Options">
<xsd:key name="PK">
<xsd:selector xpath="option"/>
<xsd:field xpath="id"/>
</xsd:key>
<xsd:keyref name="FK" refer="PK">
<xsd:selector xpath="option"/>
<xsd:field xpath="dependency"/>
</xsd:keyref>
</xsd:element>
</xsd:schema>
If you wish to have this type referenced in multiple instances, along with the constraints you've indicated, then you will have to always define a global element, and then ref that element in your specific contexts.
I would mention that it is very important to understand of your use of the "different" word in your question. If you really mean it, then the above doesn't give you that.

Content restriction and attribute validation on the same element in XSD

I would like to validate that an element 'Test' should
Have its content restricted (for example, using a pattern restriction), and
Contain certain attributes (for example, 'id', 'class' and 'name').
The XSD I'm writing looks like this:
<xsd:element name="Test" minOccurs="0" maxOccurs="unbounded">
<xsd:complexType mixed="true">
<xsd:simpleContent>
<xsd:restriction>
<xsd:pattern value="xyz"/>
</xsd:restriction>
</xsd:simpleContent>
<xsd:attribute name="id" type="xsd:string"></xsd:attribute>
<xsd:attribute name="class" type="xsd:string"></xsd:attribute>
<xsd:attribute name="name" type="xsd:string"></xsd:attribute>
</xsd:complexType>
</xsd:element>
However, when I code this in Visual Studio, I get the following error on the 'xsd:attribute' elements:
'attribute' and content model are mutually exclusive
Is there a way to validate both a content restriction and attributes on the same element?
You need to separate out your restriction and give it a name, then refer to it as a base type for an extension. Like this:
<xsd:simpleType name="RestrictedString">
<xsd:restriction base="xsd:string">
<xsd:pattern value="xyz" />
</xsd:restriction>
</xsd:simpleType>
<xsd:element name="Test">
<xsd:complexType>
<xsd:simpleContent>
<xsd:extension base="RestrictedString">
<xsd:attribute name="id" type="xsd:string" />
<xsd:attribute name="class" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:extension>
</xsd:simpleContent>
</xsd:complexType>
</xsd:element>

XSD Make minOccurs depend on containing type

I have a complex type defined which doesn't currently contain any minOccurs restrictions. When I use this comlpex type as an element type I sometimes want the elements to have minOccurs 0, other times 1. E.g.
<xsd:complexType name="Identifier">
<xsd:sequence>
<xsd:element name="Id" type="xsd:string"/>
<xsd:element name="Version" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="Wibble">
<xsd:sequence>
<xsd:element name="Id" type="Identifier"/> <!-- I want all elements of Identifier to be mandatory when used as part of a 'Wibble' -->
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="Wobble">
<xsd:sequence>
<xsd:element name="Id" type="Identifier"/> <!-- I want all elements of Identifier to be optional when used as part of a 'Wobble' -->
</xsd:sequence>
</xsd:complexType>
Is this possible?
Thanks in advance.
Groups are your friend, e.g.
<xsd:group name="IdentifierGroup">
<xsd:sequence>
<xsd:element name="Id" type="Identifier"/>
</xsd:sequence>
</xsd:group>
<xsd:complexType name="Wibble">
<xsd:sequence>
<xsd:group ref="IdentifierGroup" minOccurs="1"/>
<!-- more elements for Wibble here -->
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="Wobble">
<xsd:sequence>
<xsd:group ref="IdentifierGroup" minOccurs="0"/>
<!-- more elements for Wobble here -->
</xsd:sequence>
</xsd:complexType>

In XSD, how can I define two different elements with the same name?

I have a problem making an xsd file. I need to have an xsd file for xml documents which will look like this:
<message type="login">
<login nick="Ben" gameId="chess" desiredRole="simple "/>
</message>
or like this
<message type="error">
Error message
</message>
Meaning there is always a message tag but it has different attribute type values and depending on type value there are different things inside the message tag. I tried something like this:
<xsd:element name ='message' type='messageType'>
</xsd:element>
<xsd:complexType name='messageType'/>
<xsd:complexType name='error'>
<xsd:complexContent>
<xsd:extension base='messageType'>
<xsd:attribute name ='type' use='required'>
<xsd:simpleType>
<xsd:restriction base='xsd:string'>
<xsd:enumeration value='error'/>
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
<xsd:complexType name='login'>
<xsd:complexContent>
<xsd:extension base='messageType'>
<xsd:sequence>
<xsd:element name='login'>
<xsd:complexType>
<xsd:attribute name='nick' type='xsd:string' use='required'>
</xsd:attribute>
<xsd:attribute name='gameId' type='xsd:string' use='required'>
</xsd:attribute>
<xsd:attribute name='desiredRole' type='xsd:string' use='required'>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
<xsd:attribute name ='type' use='required'>
<xsd:simpleType>
<xsd:restriction base='xsd:string'>
<xsd:enumeration value='login'/>
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:schema>
but it doesn’t work (I get an error that the attribute type was not defined). Can some one please help me with this?
How about
<message>
<login />
</message>
and
<message>
<error />
</message>
That is, leave off the type attribute, and always have an element inside of message.
XSD doesn't allow you to do precisely what you want to do, which is create an element that has different structures depending on attribute values. However, if you truly need this element to have different structures like this, you can create an element definition that allows all possible structures. You just cannot have it automatically validated by the parser to prove that it conforms to either one definition or the other, exclusively. Not within XSD at any rate.
Try something like this:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="message" type="messageType"/>
<xsd:simpleType name="typeType">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="login"/>
<xsd:enumeration value="error"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:element name="login">
<xsd:complexType>
<xsd:attribute name='nick' type='xsd:string' use='required'/>
<xsd:attribute name='gameId' type='xsd:string' use='required'/>
<xsd:attribute name='desiredRole' type='xsd:string' use='required'/>
</xsd:complexType>
</xsd:element>
<xsd:complexType name='messageType'/>
<xsd:sequence>
<xsd:element ref="login" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="type" type="typeType" use="required"/>
</xsd:complexType>
</xsd:schema>

Resources