xsd Schema validation; xs:choice and min/max-occurs - xsd

We have an xml file that consists of one root element, a directly following element and after that 0 to 255 other elements of one specific type.
Currently, our XSD file looks like this:
<xs:element name="TIM">
...
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element ref="POINT" minOccurs="0" maxOccurs="1">
<xs:annotation>
<xs:documentation xml:lang="en">
Point
</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element ref="VALUE" minOccurs="0" maxOccurs="255">
<xs:annotation>
<xs:documentation xml:lang="en">
Value
</xs:documentation>
</xs:annotation>
</xs:element>
</xs:choice>
...
</xs:element>
How would I have to change this to say "Element Point once at the top, afterwards only ElementValue"?

Sounds like you want a simple sequence xs:sequence i.e. <xs:sequence><xs:element ref="POINT">..</xs:element><xs:element ref="VALUE" minOccurs="0" maxOccurs="255">..</xs:element></xs:sequence>.

Related

XSD: How to have (A*|B*), C?, (A*|B*)

I have a XSD with XML elements A, B, and C.
I would like these to appear in a parent element in this way:
A and B can appear any times, C only once, optionally.
The order does not matter, but A and B should ideally be "together",
(so it's rather (A*), C?, (B*) | (B*), C?, (A*)), but the "A and B together" is not necessary).
How can I achieve that with XSD?
Actual XSD what I have tried:
<!-- Hint -->
<xs:element name="hint">
<xs:complexType mixed="true">
<xs:sequence>
<xs:choice>
<xs:element ref="tag" minOccurs="0" maxOccurs="unbounded"/>
<xs:element ref="link" minOccurs="0" maxOccurs="unbounded" />
</xs:choice>
<xs:sequence>
<xs:element name="message" minOccurs="0" maxOccurs="1"/>
</xs:sequence>
<xs:choice>
<xs:element ref="tag" minOccurs="0" maxOccurs="unbounded"/>
<xs:element ref="link" minOccurs="0" maxOccurs="unbounded"/>
</xs:choice>
</xs:sequence>
</xs:complexType>
</xs:element>
But that gives me
cos-nonambig: <ns>:link and <ns>:link (or elements from their substitution group) violate "Unique Particle Attribution". During validation against this schema, ambiguity would be created for those two particles.
Basically, the need is to have any mix of A, B, C, where C appears
only once.
XSD 1.1 Solution
<?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"
vc:minVersion="1.1">
<xs:complexType name="SolutionType">
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="A"/>
<xs:element name="B"/>
<xs:element name="C"/>
</xs:choice>
<xs:assert test="count(c) <= 1"/>
</xs:complexType>
</xs:schema>
The above xs:assertion assumes that you mean "C appears at most once" but can easily be adjusted to require C to appear exactly once.
A and B can appear any times, C only once, optionally. The order does
not matter, but A and B should ideally be "together"
XSD 1.0 Solution
You'll have to impose an ordering to avoid violating Unique Particle Attribution:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:complexType name="SolutionType">
<xs:sequence>
<xs:element name="A" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="C" minOccurs="0"/>
<xs:element name="B" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
At least this achieves your preference toward keeping A and B together.
The "Unique Particle Attribution" basically means that every element during validation needs to be deterministically assignable to certain XSD "branch". And that can be checked when validating the XSD.
I found out that the (only?) way to avoid abiguity is to list all combinations of A,B,C in a <xs:choice>, while setting minOccurs="1" as appropriate to break the ambiguity. That gives quite a few choices, but for 3 elements, still doable.
This is for the case where I leave 'C' in the beginning:
<xs:sequence>
<xs:element name="message" minOccurs="0" maxOccurs="1"/>
<xs:choice>
<xs:sequence>
<xs:element ref="link" minOccurs="1" maxOccurs="unbounded" />
<xs:element ref="tag" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
<xs:sequence>
<xs:element ref="tag" minOccurs="1" maxOccurs="unbounded"/>
<xs:element ref="link" minOccurs="0" maxOccurs="unbounded" />
</xs:sequence>
<xs:sequence/>
</xs:choice>
</xs:sequence>
Not closing this question, I believe there's a better option even in XSD 1.0.

How do you make an XSD element required or not required depending on the context?

We have a definition of Person element where we want different elements to be required depending on
what they are doing. For example, if they are adding a Person, then different elements are required
to be sent versus updating a Person. Below in the example, the Person type is currently duplicated, which
of course is wrong. Is there a good way of representing this in the xsd so we can reuse the Person type.
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:complexType name="Person">
<xs:annotation>
<xs:documentation>This is the definition when changing a person</xs:documentation>
</xs:annotation>
<xs:sequence>
<xs:element name="PartyName" type="xs:string" minOccurs="0" maxOccurs="1"/>
<xs:element name="GenderCode" type="GenderCode_Type" minOccurs="0" maxOccurs="1"/>
<xs:element name="BirthDate" type="xs:date" minOccurs="0" maxOccurs="1"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="Person">
<xs:annotation>
<xs:documentation>This is the definition when adding a person</xs:documentation>
</xs:annotation>
<xs:sequence>
<xs:element name="PartyName" type="xs:string" minOccurs="1" maxOccurs="1"/>
<xs:element name="GenderCode" type="GenderCode_Type" minOccurs="1" maxOccurs="1"/>
<xs:element name="BirthDate" type="xs:date" minOccurs="0" maxOccurs="1"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
The simplest way to have two different types for Person elements is to use local declarations of Person in the two different contexts you have in mind. For example, you might say:
<xs:element name="Add">
<xs:complexType>
<xs:sequence>
<xs:element name="Person" type="AddPerson"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="Update">
<xs:complexType>
<xs:sequence>
<xs:element name="Person" type="ChangePerson"/>
</xs:sequence>
</xs:complexType>
</xs:element>
This example assumes that you have redefined your two complex types as AddPerson and ChangePerson.
If additionally you want to have the two complex types be explicitly related, you can derive them both by restriction from a generic Person type.
<xs:complexType name="Person">
<xs:annotation>
<xs:documentation>This is the generic
definition for persons</xs:documentation>
</xs:annotation>
<xs:sequence>
<xs:element name="PartyName" type="xs:string"
minOccurs="0" maxOccurs="1"/>
<xs:element name="GenderCode" type="GenderCode_Type"
minOccurs="0" maxOccurs="1"/>
<xs:element name="BirthDate" type="xs:date"
minOccurs="0" maxOccurs="1"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="ChangePerson">
<xs:annotation>
<xs:documentation>This is the definition
when changing a person</xs:documentation>
</xs:annotation>
<xs:complexContent>
<xs:restriction base="Person">
<xs:sequence>
<xs:element name="PartyName" type="xs:string"
minOccurs="0" maxOccurs="1"/>
<xs:element name="GenderCode" type="GenderCode_Type"
minOccurs="0" maxOccurs="1"/>
<xs:element name="BirthDate" type="xs:date"
minOccurs="0" maxOccurs="1"/>
</xs:sequence>
</xs:restriction>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="AddPerson">
<xs:annotation>
<xs:documentation>This is the definition
when adding a person</xs:documentation>
</xs:annotation>
<xs:complexContent>
<xs:restriction base="Person">
<xs:sequence>
<xs:element name="PartyName" type="xs:string"
minOccurs="1" maxOccurs="1"/>
<xs:element name="GenderCode" type="GenderCode_Type"
minOccurs="1" maxOccurs="1"/>
<xs:element name="BirthDate" type="xs:date"
minOccurs="0" maxOccurs="1"/>
</xs:sequence>
</xs:restriction>
</xs:complexContent>
</xs:complexType>
Here, the generic type Person is identical to the AddPerson type; I've defined AddPerson using a vacuous restriction just for the symmetry of deriving both of the operation-specific types from the generic type.
Whether having such an explicit relation among your types actually helps you achieve your goals will depend, of course, in part on what use your system makes of your schema type definitions.

XSD extend a complex type

I'm trying to extend an existing complextype in a XSD file.
I have created a new xsd file and included it at the end of all the master XSD files includes.
The problem I'm having is that it seems to add my extension but it removes the existing elements other than those defined in asset_abstract
Is what I'm trying to do possible?
Code I don't want to modify
<xs:complexType name="Feature_Cadastre_Lot" abstract="false">
<xs:annotation>
<xs:documentation>Represents the boundary of a titled, or proposed lot</xs:documentation>
</xs:annotation>
<xs:complexContent>
<xs:extension base="asset_abstract">
<xs:sequence minOccurs="1" maxOccurs="1">
<xs:element name="LotNo" type="String_32" minOccurs="1" maxOccurs="1" nillable="false">
<xs:annotation>
<xs:documentation>The lot number as described on the originating survey plan</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="PlanNo" type="String_32" minOccurs="1" maxOccurs="1" nillable="false">
<xs:annotation>
<xs:documentation>The plan number of the originating survey plan.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="CancelledLotPlan" type="String_32" minOccurs="1" maxOccurs="1" nillable="true">
<xs:annotation>
<xs:documentation>The lot on plan cancelled by this boundary if applicable.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="TitledArea_sqm" type="Float_Positive_NonZero" minOccurs="1" maxOccurs="1" nillable="false">
<xs:annotation>
<xs:documentation>The area in square metres enclosed by the boundary, as described by the survey plan.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="Geometry" type="geometry_area_multipatch_simple" minOccurs="1" maxOccurs="1" nillable="false">
<xs:annotation>
<xs:documentation>The geometry of this feature in coordinate space. May contain holes and islands. Boundaries must consist of straight lines.</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:extension>
</xs:complexContent>
Code I can import to extend the scheme.
<xs:complexType name="Feature_Cadastre_Lot">
<xs:complexContent>
<xs:extension base="asset_abstract">
<xs:sequence>
<xs:element name="LMS_ID_1" type="String_32" minOccurs="1" maxOccurs="1" nillable="false">
<xs:annotation>
<xs:documentation>The Land Management System ID as defined by the LMS Team</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="LMS_ID_2" type="String_32" minOccurs="1" maxOccurs="1" nillable="false">
<xs:annotation>
<xs:documentation>The Land Management System ID as defined by the LMS Team</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:extension>
</xs:complexContent>
OK I've created a bare bones exmaple and I still can't get it to work now using visual studio as I wanna make sure its not the tool :) , I still can't get it too work as yours is :( I must be missing something.
Basically I've added 2 files Master.xsd and local.xsd
Master wraps the remote project I can't / don't want to modify direct and local.xsd is where all our site specific stuff (redefining as it is called).
Master.xsd
<?xml version="1.0"?>
<xs:schema version="1.0.0" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:include schemaLocation="project.xsd">
</xs:include>
<xs:include schemaLocation="local.xsd">
<xs:annotation>
<xs:documentation>A File I can add my overwrites to</xs:documentation>
</xs:annotation>
</xs:include>
</xs:schema>
project.xsd
<?xml version="1.0"?>
<xs:schema version="1.0.0" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:include schemaLocation="remote.xsd">
<xs:annotation>
<xs:documentation>A File that contains the complexType I want to add elments to. But not modify otherwise</xs:documentation>
</xs:annotation>
</xs:include>
<xs:element name="Master_Project">
<xs:annotation>
<xs:documentation>The Project.</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:sequence>
<xs:element name="ProjectData">
<xs:complexType>
<xs:sequence>
<xs:element name="ExistingElement" type="ExistingElementType">
<xs:annotation>
<xs:documentation>An Existing Element That I would Like To Add To.</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
local.xsd
<?xml version="1.0"?>
<xs:schema version="1.0.0" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:redefine schemaLocation="./remote.xsd">
<xs:complexType name="ExistingElementType">
<xs:complexContent>
<xs:extension base="ExistingElementType">
<xs:sequence>
<xs:element name="newTest"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:redefine>
</xs:schema>
remote.xsd
<?xml version="1.0"?>
<xs:schema version="1.0.0" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:complexType name="ExistingElementType">
<xs:sequence>
<xs:element name="someProperty"/>
<xs:element name="someSecondProperty"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
And where I do all the redefining eventually.
If you want to keep the name of the complex type as "Feature_Cadastre_Lot" and extend it with additional content, then you are looking at redefine instead. The net effect is that all references to "Feature_Cadastre_Lot", preexisting and new, will include the newly added content.
If you want this in some, but not all of the existing content, there is no solution to it (redefine is all or nothing).
The redefine has the following layout:
<xs:redefine schemaLocation="must resolve to your XSD">
<xs:complexType name="Feature_Cadastre_Lot">
<xs:complexContent>
<xs:extension base="Feature_Cadastre_Lot">
<xs:sequence>
<xs:element name="LMS_ID_1" type="String_32" minOccurs="1" maxOccurs="1" nillable="false">
<xs:annotation>
<xs:documentation>The Land Management System ID as defined by the LMS Team</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="LMS_ID_2" type="String_32" minOccurs="1" maxOccurs="1" nillable="false">
<xs:annotation>
<xs:documentation>The Land Management System ID as defined by the LMS Team</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:redefine>
The result will look like this:
You can see the highlighted sequence as showing the added content.
In Visual Studio 2010, the content also shows ok:
Notice the second sequence at the bottom.

XSD: What's the difference between these two?

In the first one, I put the minOccurs and maxOccurs in the sequence element:
<xs:element name="Prerequisites" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:element name="Prerequisite" type="PrerequisiteType"/>
</xs:sequence>
</xs:complexType>
</xs:element>
In the second one, I put it in the contained element element:
<xs:element name="Prerequisites" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:sequence>
<xs:element name="Prerequisite" type="PrerequisiteType" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
In this particular case there is no difference, i.e. both definitions describe the same language.
What you define in first example is the limit of the occurrences of the whole sequence, in the second case only of one element of the sequence.

Question about xsd. Elements inside complex type must be allowed in any order

If you look at the following xsd fragment you can conclude that the corresponding xml will first contain cars followed by busses eg:
car,car,bus,bus
HOWEVER I want the xml to be able to contain
car,bus,car,bus
What change do I need to make in the xsd below in order to achieve this?
<xs:element name="body">
<xs:complexType>
<xs:sequence>
<xs:element name="session" type="tns:session" />
<xs:element minOccurs="0" maxOccurs="unbounded" name="car" type="tns:car" />
<xs:element minOccurs="0" maxOccurs="unbounded" name="bus" type="tns:bus" />
</xs:sequence>
</xs:complexType>
</xs:element>
It's a bit cumbersome, but you might achieve what you're looking for like this:
create a <xs:choice> element with your car and bus elements inside; this defines that one of the contained elements can be used
make sure to have the attribtues minOccurs=1 and maxOccurs=unbounded on that <xs:choice> - this gives you any number of either car or bus elements - any number, any combination
So your XML schema would look something like this (I added some stuff just to be able to generate a sample XML and verify it works - tweak as needed):
<?xml version="1.0" encoding="utf-8"?>
<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="body">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element minOccurs="0" maxOccurs="unbounded" name="car" type="CarType" />
<xs:element minOccurs="0" maxOccurs="unbounded" name="bus" type="BusType" />
</xs:choice>
</xs:complexType>
</xs:element>
<xs:complexType name="CarType">
<xs:sequence>
<xs:element name="Maker" type="xs:string" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="BusType">
<xs:sequence>
<xs:element name="Maker" type="xs:string" />
<xs:element name="Capacity" type="xs:int" />
</xs:sequence>
</xs:complexType>
</xs:schema>
use <xs:any> insted of <xs:sequence>

Resources