UML aggregation/association to XML Schema - xsd

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.

Related

XMLSchema - Element refers to itself - how to do it?

I have a task where I need to create an element "Worker" which has 0 or more subelements "subordinate". I have to use key and keyref to create the references. I can't figure out how make the references "work". Here's what I've written so far:
<xsd:element name="Workers">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Worker" maxOccurs="unbounded">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="name" type="xsd:string"/>
<xsd:element name="subordinate" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
<xsd:attribute name="identyfikator" type="PESEL" use="required"/>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:key name="id">
<xsd:selector xpath="Worker"/>
<xsd:field xpath="#identyfikator"/>
</xsd:key>
<xsd:keyref name="subordinate_ref" refer="id">
<xsd:selector xpath="Worker/subordinate"/>
<xsd:field xpath="#identyfikator"/>
</xsd:keyref>
</xsd:element>
PESEL is my own type and the key restriction works well as I am unable to create two workers with the same key in XML document. However, I can create anything as "subordinate" element and no warnings will be displayed. As I understand, in case of such reference I should be only able to add workers as subordinates if they already exist, right? How do I create proper reference?
This is my first time working with XMLSchema so sorry if the code is messy.
Thanks in advance!
Make a Worker ComplexType and have Worker and Subordinate both be of that type.
Approximately like so:
<!-- Define the below where appropriate. -->
<xsd:element name="Worker" type="WorkerType" />
<xsd:complexType name="WorkerType">
<xsd:sequence>
<xsd:element name="name" type="xsd:string"/>
<xsd:element name="subordinate" type="WorkerType" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
<xsd:attribute name="identyfikator" type="PESEL" use="required"/>
</xsd:complexType>
Also, if you want items to have a unique id, then consider using (or extending) the xsd:ID datatype. This gives you free uniqueness and referential checks using xsd:IDREF.
<xsd:attribute name="identyfikator" type="xsd:ID" use="required"/>

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.

XML Schema Choice - choose at lease one, but no repeat

How can I enforce to chose at lease one, but no repeat?
The following syntax allows any c element to repeat up to 3 times.
<choice minOccurs="1" maxOccurs="3">
<element name="c1" type="string" />
<element name="c2" type="string" />
<element name="c3" type="string" />
</choice>
thnx
steve
Loose the maxOccurs="3" and what you got is "choose at least one", no repeat.
For particles, the default is minOccurs="1"; a mandatory choice, where each option particle is itself mandatory, is your answer.
UPDATE: Based on your comment, if what you're looking is for any ordered combination of the particles you've described, this is the best you can get with XSD spec.
<?xml version="1.0" encoding="utf-8" ?>
<xsd:schema targetNamespace="http://tempuri.org/XMLSchema.xsd" elementFormDefault="qualified" xmlns="http://tempuri.org/XMLSchema.xsd" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="root">
<xsd:complexType>
<xsd:choice>
<xsd:sequence>
<xsd:element ref="c1"/>
<xsd:element ref="c2" minOccurs="0"/>
<xsd:element ref="c3" minOccurs="0"/>
</xsd:sequence>
<xsd:sequence>
<xsd:element ref="c2"/>
<xsd:element ref="c3" minOccurs="0"/>
</xsd:sequence>
<xsd:element ref="c3"/>
</xsd:choice>
</xsd:complexType>
</xsd:element>
<xsd:element name="c1" type="xsd:string"/>
<xsd:element name="c2" type="xsd:string"/>
<xsd:element name="c3" type="xsd:string"/>
</xsd:schema>
This is messy already; if you're looking for a greater number of particles or any unordered combination, then I would change the model to something like this (these are XSD 1.0 limitations in action - it all has to do with limitations in the XPath syntax you can use for selectors/fields).
<?xml version="1.0" encoding="utf-8" ?>
<xsd:schema targetNamespace="http://tempuri.org/XMLSchema.xsd" elementFormDefault="qualified" xmlns="http://tempuri.org/XMLSchema.xsd" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="root">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="c" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:key name="pk">
<xsd:selector xpath="*"/>
<xsd:field xpath="#code"/>
</xsd:key>
</xsd:element>
<xsd:element name="c" type="TC" abstract="true"/>
<xsd:element name="c1" type="TC1" substitutionGroup="c"/>
<xsd:element name="c2" type="TC2" substitutionGroup="c"/>
<xsd:element name="c3" type="TC3" substitutionGroup="c"/>
<xsd:complexType name="TC">
<xsd:simpleContent>
<xsd:extension base="xsd:string">
<xsd:attribute name="code" type="xsd:string"/>
</xsd:extension>
</xsd:simpleContent>
</xsd:complexType>
<xsd:complexType name="TC1">
<xsd:simpleContent>
<xsd:restriction base="TC">
<xsd:attribute name="code" type="xsd:string" fixed="c1"/>
</xsd:restriction>
</xsd:simpleContent>
</xsd:complexType>
<xsd:complexType name="TC2">
<xsd:simpleContent>
<xsd:restriction base="TC">
<xsd:attribute name="code" type="xsd:string" fixed="c2"/>
</xsd:restriction>
</xsd:simpleContent>
</xsd:complexType>
<xsd:complexType name="TC3">
<xsd:simpleContent>
<xsd:restriction base="TC">
<xsd:attribute name="code" type="xsd:string" fixed="c3"/>
</xsd:restriction>
</xsd:simpleContent>
</xsd:complexType>
</xsd:schema>
A sample XML would like this:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<!-- Sample XML generated by QTAssistant (http://www.paschidev.com) -->
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://tempuri.org/XMLSchema.xsd">
<c1 code="c1">c11</c1>
<c2 code="c2">c21</c2>
<c3 code="c3">c21</c3>
</root>
or this:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<!-- Sample XML generated by QTAssistant (http://www.paschidev.com) -->
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://tempuri.org/XMLSchema.xsd">
<c2 code="c2">c21</c2>
<c1 code="c1">c11</c1>
</root>
Basically you're keying in on some component that makes your element unique, that is part of the data as opposed to a tag name. Again, messy, but as an exercise, it may give you an idea.

Any order + constraints for each element

I am trying to create an XSD, which allows child elements to be in any order. But each child element has its own minOccurs and maxOccurs.
My XSD:
<xsd:complexType name="Samples">
<xsd:sequence >
<xsd:element name="Sample1" minOccurs="1" maxOccurs="1">
<xsd:complexType>
<xsd:simpleContent>
<xsd:extension base="xsd:boolean" />
</xsd:simpleContent>
</xsd:complexType>
</xsd:element>
<xsd:element name="Sample2" minOccurs="0" maxOccurs="unbounded">
<xsd:complexType>
<xsd:simpleContent>
<xsd:extension base="xsd:string" />
</xsd:simpleContent>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
For Example a valid XML:
<Samples>
<Sample2></Sample2>
<Sample1></Sample1>
<Sample2></Sample2>
</Samples>
For Example a not valid XML (Sample1 can be choose only one time):
<Samples>
<Sample2></Sample2>
<Sample1></Sample1>
<Sample2></Sample2>
<Sample1></Sample1>
</Samples>
But i don't know, how i can mix the order, while all elements have its own constraint.
Thanks for help
What if you try this:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="Samples">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Sample2" minOccurs="0" maxOccurs="unbounded"/>
<xsd:element name="Sample1" minOccurs="1" maxOccurs="1"/>
<xsd:element name="Sample2" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
Of course, you should add your restrictions to each element:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:complexType name="Sample1Type">
<xsd:simpleContent>
<xsd:extension base="xsd:boolean" />
</xsd:simpleContent>
</xsd:complexType>
<xsd:complexType name="Sample2Type">
<xsd:simpleContent>
<xsd:extension base="xsd:string" />
</xsd:simpleContent>
</xsd:complexType>
<xsd:element name="Samples">
<xsd:complexType>
<xsd:sequence>
<xsd:element type="Sample2Type" name="Sample2" minOccurs="0" maxOccurs="unbounded"/>
<xsd:element type="Sample1Type" name="Sample1" minOccurs="1" maxOccurs="1"/>
<xsd:element type="Sample2Type" name="Sample2" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
OR even shorter for simple types:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="Samples">
<xsd:complexType>
<xsd:sequence>
<xsd:element type="xsd:string" name="Sample2" minOccurs="0" maxOccurs="unbounded"/>
<xsd:element type="xsd:boolean" name="Sample1" minOccurs="1" maxOccurs="1"/>
<xsd:element type="xsd:string" name="Sample2" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
P.S.::
There are unfortunately no XSD elements like xsd:sequence, which will allow, what you ask.
What you want looks like xsd:all; however, since xsd:all only works for elements for which maxOccurs is 1, it will not work here. If you can combine choices and sequences to constrain your content, one way to go around duplication of definition (avoid defining twice) is to define Sample1 and Sample 2 as global elements and then ref them under your compositors. If defining global elements is not an option except for your root elements, then you could at least define the types globally - this way you maximize the reuse, and somewhat getting closer to your requirement "without defining twice"...

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>

Resources