Writing an .xsd for elements with attributes - attributes

I'm currently familiarising myself with xsd and xml just for fun, and I'm not sure what I'm doing wrong. I'd like to write an xsd for a simple (well, not really, since it has attributes) table with rows and columns and use XML mapping in Excel to display the data nicely. Rows for rows, and columns for columns like in tables one will usually see. e.g.
<?xml version='1.0'?>
<table name='Data1'>
<row>
<col name='id'>1</col>
<col name='x'>0</col>
<col name='y'>6</col>
<col name='z'>7</col></row>
<row>
<col name='id'>2</col>
<col name='x'>0</col>
<col name='y'>5</col>
<col name='z'>8</col></row>
<row>
<col name='id'>3</col>
<col name='x'>0</col>
<col name='y'>5</col>
<col name='z'>9</col></row></table>
In effect, it should look something like:
id | x | y | z
1 | 0 | 6 | 7
2 | 0 | 5 | 8
3 | 0 | 5 | 9
Edited schema:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="table">
<xs:complexType>
<xs:sequence>
<xs:element name="row" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="col" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="name" type="xs:string"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="name" type="xs:string"/>
</xs:complexType>
</xs:element>
</xs:schema>
Did I add some extra ingredient or am missing something? I'm not really clear about this xsd thing yet. XD
Thanks in advance for anyone who could point out my mistake(s).

An xml is not validated by the scheme -- column element declaration is not complete.
Try this one:
<xs:element name='table'>
<xs:complexType>
<xs:sequence>
<xs:element name='row'>
<xs:complexType>
<xs:sequence>
<xs:element name='col' minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="name" type="xs:string">
</xs:attribute>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name='name' type='xs:string'/>
</xs:complexType>
</xs:element>

Related

Make element required when attribute is set to some value using XSD (1.1)

I have a following schema (1.1). I would like to have schema that will check that a sequence of parameters has mendatory parameter of type '1' and optional parameter of type '2'. I did it using alternatives because different types have different list of attributes.
How write an assertion to check that parameter of type 1 is mendatory?
<?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" vc:minVersion="1.1">
<xs:element name="rule">
<xs:complexType>
<xs:sequence>
<xs:element name="conditions" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="condition" maxOccurs="unbounded" minOccurs="1">
<xs:complexType>
<xs:sequence>
<xs:element name="parameter" maxOccurs="unbounded" minOccurs="1">
<xs:alternative test="#type = '1'" type="typeOne"/>
<xs:alternative test="#type = '2'" type="typeTwo" />
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="typeOne">
<xs:attribute name="type" type="xs:string" use="required"/>
</xs:complexType>
<xs:complexType name="typeTwo">
<xs:attribute name="type" type="xs:string" use="required" />
</xs:complexType>
</xs:schema>
I did it using alternatives because different types have different list of attributes.
It would be like this:
<xs:element name="condition" maxOccurs="unbounded" minOccurs="1">
<xs:complexType>
<xs:sequence>
<xs:element name="parameter" maxOccurs="unbounded" minOccurs="1">
<xs:alternative test="#type = '1'" type="typeOne"/>
<xs:alternative test="#type = '2'" type="typeTwo" />
</xs:element>
</xs:sequence>
<xs:assert id="type-1-mandatory" test="parameter[#type eq '1']"></xs:assert>
</xs:complexType>
</xs:element>

XSD for elements string with attribute id

I would like to write a XSD element that permit something like that :
<CustomFields>
<CustomField id="1">some text data</CustomField>
<CustomField id="2">some text data</CustomField>
</CustomFields>
But I have some restrictions : I have to restrict the text (maxLenght = 36). And I would like to be impossible to have 2 CustomField with the same id.
So far I wrote this, but it not what I want :
<xs:element name="CustomFields" minOccurs="0">
<xs:complexType>
<xs:sequence>
<xs:element name="CustomField" minOccurs="0" maxOccurs="20">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="id" type="xs:integer" use="required"></xs:attribute>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
Thanks for any help.
Regards.
You could use following attempt
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:simpleType name="restrictedString">
<!-- Make a new type to be a "descendant" of string-->
<xs:restriction base="xs:string">
<xs:maxLength value="36"/>
</xs:restriction>
</xs:simpleType>
<xs:element name="CustomFields">
<xs:complexType>
<xs:sequence>
<xs:element name="CustomField" minOccurs="0" maxOccurs="20">
<xs:complexType>
<xs:simpleContent>
<!-- reference new type you declared above -->
<xs:extension base="restrictedString">
<xs:attribute name="id" type="xs:integer" use="required"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
<!-- Restrict #id to be unique-->
<xs:unique name="id_uq">
<xs:selector xpath="CustomField"/>
<xs:field xpath="#id"/>
</xs:unique>
</xs:element>
</xs:schema>

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>

Validate repeating optional elements XML-Schema

I am try to create an xsd schema that validates the following xml:
<results>
<row>
<PersonID key="true">1</PersonID>
<FirstName>John</FirstName>
<Surname>Smith</Surname>
<LogonName>jsmith</LogonName>
</row>
<row>
<PersonID key="true">2</PersonID>
<FirstName>Steve</FirstName>
<Surname>Jones</Surname>
<LogonName>sjones</LogonName>
</row>
The results node and row node are mandatory, but the nodes inside each row are optional and may have other nodes that I have not listed. There could 1 row or many rows.
I have created the below but I am unable to validate correctly:
<xs:element name="results">
<xs:complexType>
<xs:sequence>
<xs:element name="row" maxOccurs="unbounded" minOccurs="0">
<xs:complexType>
<xs:sequence>
<xs:element name="PersonID" minOccurs="0">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:byte">
<xs:attribute type="xs:string" name="key" use="optional"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:choice minOccurs="0">
<xs:element type="xs:string" name="FirstName" minOccurs="0"/>
<xs:element type="xs:string" name="Surname" minOccurs="0"/>
<xs:element type="xs:string" name="LogonName" minOccurs="0"/>
<xs:element type="xs:string" name="GroupName" minOccurs="0"/>
</xs:choice>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
Thanks.
If PersonID, FirstName etc. can occurr at most once - and in that specific order - try this:
<xs:element name="results">
<xs:complexType>
<xs:sequence>
<xs:element name="row" maxOccurs="unbounded" minOccurs="0">
<xs:complexType>
<xs:sequence>
<xs:element name="PersonID" minOccurs="0">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:byte">
<xs:attribute type="xs:string" name="key" use="optional"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:element type="xs:string" name="FirstName" minOccurs="0"/>
<xs:element type="xs:string" name="Surname" minOccurs="0"/>
<xs:element type="xs:string" name="LogonName" minOccurs="0"/>
<xs:element type="xs:string" name="GroupName" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
(basically just drop the choice element). If PersonID, FirstName etc. can occurr at most once but in any order you can use all:
<xs:element name="results">
<xs:complexType>
<xs:sequence>
<xs:element name="row" maxOccurs="unbounded" minOccurs="0">
<xs:complexType>
<xs:all>
<xs:element name="PersonID" minOccurs="0">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:byte">
<xs:attribute type="xs:string" name="key" use="optional"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:element type="xs:string" name="FirstName" minOccurs="0"/>
<xs:element type="xs:string" name="Surname" minOccurs="0"/>
<xs:element type="xs:string" name="LogonName" minOccurs="0"/>
<xs:element type="xs:string" name="GroupName" minOccurs="0"/>
</xs:all>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
If you don't know elements can occur within row you can use:
<xs:element name="results">
<xs:complexType>
<xs:sequence>
<xs:element name="row" maxOccurs="unbounded" minOccurs="0">
<xs:complexType>
<xs:sequence>
<xs:any minOccurs="0" maxOccurs="unbounded" processContents="skip"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
that accepts any element within row.

Resources