Vous êtes sur la page 1sur 25

XML Schema Basics

In this lesson of the XML tutorial, you will learn...


1. The purpose of XML Schema.
2. The limitations of DTDs.
3. The power of XML Schema.
4. How to validate an XML Instance with an XML schema.
The Purpose of XML Schema
XML Schema is an XML-based language used to create XML-based languages and data
models.
An XML schema defines element and attribute names for a class of XML documents.
The
schema also specifies the structure that those documents must adhere to and the
type of content
that each element can hold.
XML documents that attempt to adhere to an XML schema are said to be instances o
f that
schema. If they correctly adhere to the schema, then they are valid instances. T
his is not the same
as being well formed. A well-formed XML document follows all the syntax rules of
XML, but it
does necessarily adhere to any particular schema. So, an XML document can be wel
l formed
without being valid, but it cannot be valid unless it is well formed.
The Power of XML Schema
You may already have some experience with DTDs. DTDs are similar to XML schemas
in that
they are used to create classes of XML documents. DTDs were around long before t
he advent of
XML. They were originally created to define languages based on SGML, the parent
of XML.
Although DTDs are still common, XML Schema is a much more powerful language.
As a means of understanding the power of XML Schema, let's look at the limitatio
ns of DTD.
1. DTDs do not have built-in datatypes.
2. DTDs do not support user-derived datatypes.
3. DTDs allow only limited control over cardinality (the number of occurren
ces of an
element within its parent).
4. DTDs do not support Namespaces or any simple way of reusing or importing
other
schemas.
A First Look
An XML schema describes the structure of an XML instance document by defining wh
at each
element must or may contain. An element is limited by its type. For example, an
element of
complex type can contain child elements and attributes, whereas a simple-type el
ement can only
contain text. The diagram below gives a first look at the types of XML Schema el
ements.

Schema authors can define their own types or use the built-in types. Throughout
this course, we
will refer back to this diagram as we learn to define elements. You may want to
bookmark this
page, so that you can easily reference it.
The following is a high-level overview of Schema types.
1. Elements can be of simple type or complex type.
2. Simple type elements can only contain text. They can not have child elem
ents or
attributes.
3. All the built-in types are simple types (e.g, xs:string).
4. Schema authors can derive simple types by restricting another simple typ
e. For example,
an email type could be derived by limiting a string to a specific pattern.
5. Simple types can be atomic (e.g, strings and integers) or non-atomic (e.
g, lists).
6. Complex-type elements can contain child elements and attributes as well
as text.
7. By default, complex-type elements have complex content, meaning that the
y have child
elements.
8. Complex-type elements can be limited to having simple content, meaning t
hey only
contain text. They are different from simple type elements in that they have att
ributes.
9. Complex types can be limited to having no content, meaning they are empt
y, but they
have may have attributes.
10. Complex types may have mixed content - a combination of text and child e
lements.
A Simple XML Schema
Let's take a look at a simple XML schema, which is made up of one complex type e
lement with
two child simple type elements.
Code Sample: SchemaBasics/Demos/Author.xsd
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Author">
<xs:complexType>
<xs:sequence>
<xs:element name="FirstName" type="xs:string" />
<xs:element name="LastName" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Code Explanation
As you can see, an XML schema is an XML document and must follow all the syntax
rules of
any other XML document; that is, it must be well formed. XML schemas also have t
o follow the
rules defined in the "Schema of schemas," which defines, among other things, the
structure of
and element and attribute names in an XML schema.
Although it is not required, it is a common practice to use the xs qualifier (se
e footnote) to
identify Schema elements and types.
The document element of XML schemas is xs:schema. It takes the attribute xmlns:x
s with the
value of http://www.w3.org/2001/XMLSchema, indicating that the document should f
ollow the
rules of XML Schema. This will be clearer after you learn about namespaces.
In this XML schema, we see a xs:element element within the xs:schema element. xs
:element is
used to define an element. In this case it defines the element Author as a compl
ex type element,
which contains a sequence of two elements: FirstName and LastName, both of which
are of the
simple type, string.
Validating an XML Instance Document
In the last section, you saw an example of a simple XML schema, which defined th
e structure of
an Author element. The code sample below shows a valid XML instance of this XML
schema.
Code Sample: SchemaBasics/Demos/MarkTwain.xml
<?xml version="1.0"?>
<Author xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="Author.xsd">
<FirstName>Mark</FirstName>
<LastName>Twain</LastName>
</Author>
Code Explanation
This is a simple XML document. Its document element is Author, which contains tw
o child
elements: FirstName and LastName, just as the associated XML schema requires.
The xmlns:xsi attribute of the document element indicates that this XML document
is an instance
of an XML schema. The document is tied to a specific XML schema with the
xsi:noNamespaceSchemaLocation attribute.
There are many ways to validate the XML instance. If you are using an XML author
ing tool, it
very likely is able to perform the validation for you. Alternatively, a couple o
f simple online
XML Schema validator tools are listed below.
* http://tools.decisionsoft.com/schemaValidate.html provided by DecisionSo
ft.
* http://apps.gotdotnet.com/xmltools/xsdvalidator provided by GotDotNet.
XML Schema Basics Conclusion
In this lesson of the XML tutorial, you have learned to create a very simple XML
Schema and to
use it to validate an XML instance document. You are now ready to learn more adv
anced
features of XML Schema.
Footnotes
1. Qualifiers are used to distinguish between elements and attributes from
different
namespaces or XML classes.
To continue to learn XML go to the top of this page and click on the next lesson
in this XML
Tutorial's Table of Contents.
















Simple Types




Simple-Type Elements
In this lesson of the XML tutorial, you will learn...
1. To use XML Schema's built-in simple types.
2. To derive your own types.
3. To define list types.
4. To define union types.
5. To declare global simple-type elements.
6. To set default and fixed values.
7. To allow for nil values.
Overview
Simple-type elements have no children or attributes. For example, the Name eleme
nt below is a
simple-type element; whereas the Person and HomePage elements are not.
Code Sample: SimpleTypes/Demos/SimpleType.xml
<?xml version="1.0"?>
<Person>
<Name>Mark Twain</Name>
<HomePage URL="http://www.marktwain.com"/>
</Person>
Code Explanation
As the diagram below shows, a simple type can either be built-in or user-derived
. In this lesson,
we will examine both.
Built-in Simple Types
XML Schema specifies 44 built-in types, 19 of which are primitive.
19 Primitive Data Types
The 19 built-in primitive types are listed below.
1. string
2. boolean
3. decimal
4. float
5. double
6. duration
7. dateTime
8. time
9. date
10. gYearMonth
11. gYear
12. gMonthDay
13. gDay
14. gMonth
15. hexBinary
16. base64Binary
17. anyURI
18. QName
19. NOTATION
Built-in Derived Data Types
The other 25 built-in data types are derived from one of the primitive types lis
ted above.
1. normalizedString
2. token
3. language
4. NMTOKEN
5. NMTOKENS
6. Name
7. NCName
8. ID
9. IDREF
10. IDREFS
11. ENTITY
12. ENTITIES
13. integer
14. nonPositiveInteger
15. negativeInteger
16. long
17. int
18. short
19. byte
20. nonNegativeInteger
21. unsignedLong
22. unsignedInt
23. unsignedShort
24. unsignedByte
25. positiveInteger
Defining a Simple-type Element
A simple-type element is defined using the type attribute.
Code Sample: SimpleTypes/Demos/Author.xsd
<?xml version="1.0" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Author">
<xs:complexType>
<xs:sequence>
<xs:element name="FirstName" type="xs:string"/>
<xs:element name="LastName" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Code Explanation
Notice the FirstName and LastName elements in the code sample below. They are no
t explicitly
defined as simple type elements. Instead, the type is defined with the type attr
ibute. Because the
value (string in both cases) is a simple type, the elements themselves are simpl
e-type elements.
The Author element is a complex-type element. Complex-type elements will be cove
red in
"Complex-Type Elements".
Exercise: Building a Simple Schema
Duration: 10 to 15 minutes.
In this exercise, you will build a simple XML schema.
1. Open SimpleTypes/Exercises/Song.xsd for editing.
2. Between the open and close xs:sequence tags, declare three new elements:
o Title of type xs:string.
o Year of type xs:gYear.
o Artist of type xs:string.
3. Save the file.
4. Try to validate LoveMeDo.xml against the schema you just created. If the
XML document is
invalid, fix your schema.
Code Sample: SimpleTypes/Exercises/Song.xsd
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Song">
<xs:complexType>
<xs:sequence>
<!--
Add three simple-type elements:
1. Title
2. Year
3. Artist
-->
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Where is the solution?
User-derived Simple Types
A schema author can derive a new simple type using the <xs:simpleType> element.
This simple
type can then be used in the same way that built-in simple types are.
Simple types are derived by restricting built-in simple types or other user-deri
ved simple types.
For example, you might want to create a simple type called password that is an e
ight-character
string. To do so, you would start with the xs:string type and restrict its lengt
h to eight characters.
This is done nesting the <xs:restriction> element inside of the <xs:simpleType>
element.
Code Sample: SimpleTypes/Demos/Password.xsd
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:simpleType name="Password">
<xs:restriction base="xs:string">
<xs:length value="8"/>
</xs:restriction>
</xs:simpleType>
<xs:element name="User">
<xs:complexType>
<xs:sequence>
<xs:element name="PW" type="Password"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Code Sample: SimpleTypes/Demos/Password.xml
<?xml version="1.0"?>
<User xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="Password.xsd">
<PW>MyPasWrd</PW>
</User>
Applying Facets
Simple types can be derived by applying one or more of the following facets.
* length
* minLength
* maxLength
* pattern
* enumeration
* whiteSpace
* minInclusive
* minExclusive
* maxInclusive
* maxExclusive
* totalDigits
* fractionDigits
Controlling Length
The length of a string can be controlled with the length, minLength, and maxLeng
th facets. We
used the length facet in the example above to create a Password simple type as a
n eight-character
string. We could use minLength and maxLength to allow passwords that were betwee
n six and
twelve characters in length.
The schema below shows how this is done. The two XML instances shown below it ar
e both
valid, because the length of the password is between six and twelve characters.
Code Sample: SimpleTypes/Demos/Password2.xsd
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:simpleType name="Password">
<xs:restriction base="xs:string">
<xs:minLength value="6"/>
<xs:maxLength value="12"/>
</xs:restriction>
</xs:simpleType>
<xs:element name="User">
<xs:complexType>
<xs:sequence>
<xs:element name="PW" type="Password"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Code Sample: SimpleTypes/Demos/Password2.xml
<?xml version="1.0"?>
<User xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="Password2.xsd">
<PW>MyPass</PW>
</User>
Code Sample: SimpleTypes/Demos/Password2b.xml
<?xml version="1.0"?>
<User xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="Password2.xsd">
<PW>MyPassWord</PW>
</User>
Specifying Patterns
Patterns are specified using the xs:pattern element and regular expressions. (se
e footnote) For
example, you could use the xs:pattern element to restrict the Password simple ty
pe to consist of
between six and twelve characters, which can only be lowercase and uppercase let
ters and
underscores.
Code Sample: SimpleTypes/Demos/Password3.xsd
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:simpleType name="Password">
<xs:restriction base="xs:string">
<xs:pattern value="[A-Za-z_]{6,12}"/>
</xs:restriction>
</xs:simpleType>
<xs:element name="User">
<xs:complexType>
<xs:sequence>
<xs:element name="PW" type="Password"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Code Sample: SimpleTypes/Demos/Password3.xml
<?xml version="1.0"?>
<User xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="Password3.xsd">
<PW>MyPassword</PW>
</User>
Working with Numbers
Numeric simple types can be derived by limiting the value to a certain range usi
ng minExclusive,
minInclusive, maxExclusive, and maxInclusive. You can also limit the total numbe
r of digits and
the number of digits after the decimal point using totalDigits and fractionDigit
s, respectively.
Mins and Maxs
The following example shows how to derive a simple type called Salary, which is
a decimal
between 10,000 and 90,000.
Code Sample: SimpleTypes/Demos/Employee.xsd
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:simpleType name="Salary">
<xs:restriction base="xs:decimal">
<xs:minInclusive value="10000"/>
<xs:maxInclusive value="90000"/>
</xs:restriction>
</xs:simpleType>
<xs:element name="Employee">
<xs:complexType>
<xs:sequence>
<xs:element name="Salary" type="Salary"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Code Sample: SimpleTypes/Demos/JohnSmith.xml
<?xml version="1.0"?>
<Employee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="Employee.xsd">
<Salary>55000</Salary>
</Employee>
Number of Digits
Using totalDigits and fractionDigits, we can further specify that the Salary typ
e should consist of
seven digits, two of which come after the decimal point. Both totalDigits and fr
actionDigits are
maximums. That is, if totalDigits is specified as 5 and fractionDigits is specif
ied as 2, a valid
number could have no more than five digits total and no more than two digits aft
er the decimal
point.
Code Sample: SimpleTypes/Demos/Employee2.xsd
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:simpleType name="Salary">
<xs:restriction base="xs:decimal">
<xs:minInclusive value="10000"/>
<xs:maxInclusive value="90000"/>
<xs:fractionDigits value="2"/>
<xs:totalDigits value="7"/>
</xs:restriction>
</xs:simpleType>
<xs:element name="Employee">
<xs:complexType>
<xs:sequence>
<xs:element name="Salary" type="Salary"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Code Sample: SimpleTypes/Demos/MarySmith.xml
<?xml version="1.0"?>
<Employee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="Employee2.xsd">
<Salary>55000.00</Salary>
</Employee>
Enumerations
A derived type can be a list of possible values. For example, the JobTitle eleme
nt could be a list
of pre-defined job titles.
Code Sample: SimpleTypes/Demos/Employee3.xsd
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:simpleType name="Salary">
<xs:restriction base="xs:decimal">
<xs:minInclusive value="10000"/>
<xs:maxInclusive value="90000"/>
<xs:fractionDigits value="2"/>
<xs:totalDigits value="7"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="JobTitle">
<xs:restriction base="xs:string">
<xs:enumeration value="Sales Manager"/>
<xs:enumeration value="Salesperson"/>
<xs:enumeration value="Receptionist"/>
<xs:enumeration value="Developer"/>
</xs:restriction>
</xs:simpleType>
<xs:element name="Employee">
<xs:complexType>
<xs:sequence>
<xs:element name="Salary" type="Salary"/>
<xs:element name="Title" type="JobTitle"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Code Sample: SimpleTypes/Demos/SteveSmith.xml
<?xml version="1.0"?>
<Employee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="Employee3.xsd">
<Salary>90000.00</Salary>
<Title>Sales Manager</Title>
</Employee>
Whitespace-handling
By default, whitespace in elements of the datatype xs:string is preserved in XML
documents;
however, this can be changed for datatypes derived from xs:string. This is done
with the
xs:whiteSpace element, the value of which must be one of the following.
* preserve - whitespace is not normalized. That is to say, it is kept as i
s.
* replace - all tabs, line feeds, and carriage returns are replaced by sin
gle spaces.
* collapse - all tabs, line feeds, and carriage returns are replaced by si
ngle spaces and then all
groups of single spaces are replaced with one single space. All leading and trai
ling spaces are
then removed (i.e, trimmed).
In SimpleTypes/Demos/Password.xsd, we looked at restricting the length of a Pass
word datatype
to eight characters using the xs:length element. If whitespace is preserved, the
n leading and
trailing spaces are considered part of the password. In the following example, w
e set
xs:whiteSpace to collapse, thereby discounting any leading or trailing whitespac
e. As you can
see, this allows the XML instance author to format the document without consider
ation of
whitespace.
Code Sample: SimpleTypes/Demos/Password4.xsd
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:simpleType name="Password">
<xs:restriction base="xs:string">
<xs:length value="8"/>
<xs:whiteSpace value="collapse"/>
</xs:restriction>
</xs:simpleType>
<xs:element name="User">
<xs:complexType>
<xs:sequence>
<xs:element name="PW" type="Password"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Code Sample: SimpleTypes/Demos/Password4.xml
<?xml version="1.0"?>
<User xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="Password4.xsd">
<PW>
12345678
</PW>
</User>
Exercise: Restricting Element Content
Duration: 15 to 20 minutes.
In this exercise, you will further restrict the Song schema, so that the Title a
nd Artist elements
will have a specified pattern and the Year will be 1950 or later.
1. Open SimpleTypes/Exercises/Song.xsd and save it as Song2.xsd in the same
directory.
2. Define a simple type called ProperName that follows this pattern. Note t
hat the only space in
the pattern is the one before the question mark.
([A-Z0-9][A-Za-z0-9\-']* ?)+
3. Change the Title and Artist elements to be of the ProperName type.
4. Define another simple type called Year, which is derived from gYear and
only accepts years
between 1950 and 2010, inclusive.
5. Change the Year element to be of the Year type.
6. Try to validate SimpleTypes/Exercises/CantBuyMeLove.xml against the sche
ma you just
created. If the XML document is invalid, fix your schema.
Code Sample: SimpleTypes/Exercises/Song.xsd
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Song">
<xs:complexType>
<xs:sequence>
<!--
Add three simple-type elements:
1. Title
2. Year
3. Artist
-->
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Where is the solution?
Specifying Element Type Locally
So far in this lesson, we have been defining simple types globally and then sett
ing the type
attribute of element declarations to be of our derived simple types. This makes
it easy to reuse a
simple type across multiple elements, as we saw with the ProperName type in the
last exercise.
It is also possible to define the type of an element locally. The type is then u
nnamed and
applicable only to that element. The only reason to do this is to clearly show t
hat the type is
specific to that element and not meant for reuse.
Code Sample: SimpleTypes/Demos/PasswordLocal.xsd
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="User">
<xs:complexType>
<xs:sequence>
<xs:element name="PW">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:length value="8"/>
<xs:whiteSpace value="collapse"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Nonatomic Types
All of XML Schema's built-in types are atomic, meaning that they cannot be broke
n down into
meaningful bits. XML Schema provides for two nonatomic types: lists and unions.
Lists
List types are sequences of atomic types separated by whitespace; you can have a
list of integers
or a list of dates. Lists should not be confused with enumerations. Enumerations
provide optional
values for an element. Lists represent a single value within an element.
Code Sample: SimpleTypes/Demos/EmployeeList.xsd
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:simpleType name="Salary">
<xs:restriction base="xs:decimal">
<xs:minInclusive value="10000"/>
<xs:maxInclusive value="90000"/>
<xs:fractionDigits value="2"/>
<xs:totalDigits value="7"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="JobTitle">
<xs:restriction base="xs:string">
<xs:enumeration value="Sales Manager"/>
<xs:enumeration value="Salesperson"/>
<xs:enumeration value="Receptionist"/>
<xs:enumeration value="Developer"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="DateList">
<xs:list itemType="xs:date"/>
</xs:simpleType>
<xs:element name="Employee">
<xs:complexType>
<xs:sequence>
<xs:element name="Salary" type="Salary"/>
<xs:element name="Title" type="JobTitle"/>
<xs:element name="VacationDays" type="DateList"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Code Sample: SimpleTypes/Demos/SandySmith.xml
<?xml version="1.0"?>
<Employee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="EmployeeList.xsd">
<Salary>44000</Salary>
<Title>Salesperson</Title>
<VacationDays>2006-8-13 2006-08-14 2006-08-15</VacationDays>
</Employee>
Unions
Union types are groupings of types, essentially allowing for the value of an ele
ment to be of more
than one type. In the example below, two atomic simple types are derived: Runnin
gRace and
Gymnastics. A third simple type, Event, is then derived as a union of the previo
us two. The
Event element is of the Event type, which means that it can either be of the Run
ningRace or the
Gymnastics type.
Code Sample: SimpleTypes/Demos/Program.xsd
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:simpleType name="RunningRace">
<xs:restriction base="xs:string">
<xs:enumeration value="100 meters"/>
<xs:enumeration value="10 kilometers"/>
<xs:enumeration value="440 yards"/>
<xs:enumeration value="10 miles"/>
<xs:enumeration value="Marathon"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="Gymnastics">
<xs:restriction base="xs:string">
<xs:enumeration value="Vault"/>
<xs:enumeration value="Floor"/>
<xs:enumeration value="Rings"/>
<xs:enumeration value="Beam"/>
<xs:enumeration value="Uneven Bars"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="Event">
<xs:union memberTypes="RunningRace Gymnastics"/>
</xs:simpleType>
<xs:element name="Program">
<xs:complexType>
<xs:sequence>
<xs:element name="Event" type="Event"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Code Sample: SimpleTypes/Demos/100Meters.xml
<?xml version="1.0"?>
<Program xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="Program.xsd">
<Event>100 meters</Event>
</Program>
Exercise: Adding Nonatomic Types
Duration: 10 to 15 minutes.
In this exercise, you will add a nonatomic type to the song schema.
1. Open SimpleTypes/Exercises/Song2.xsd and save it as Song3.xsd in the sam
e directory.
2. Define a new simple type called SongLength, which is an enumeration of t
hree values: "Short",
"Medium', and "Long".
3. Define another new simple type called SongTime, which is a union of xs:d
uration and
SongLength.
4. At the end of the sequence of elements within the Song element, insert a
n additional
element, Length, which is of the SongTime datatype.
5. Try to validate SimpleTypes/Exercises/TicketToRide.xml and
SimpleTypes/Exercises/EleanorRigby.xml against the schema you just created. If e
ither XML
document is invalid, fix your schema.
Where is the solution?
Declaring Global Simple-Type Elements
When an element declaration is a child of the xs:schema element, the declared el
ement is global.
Global elements can be referenced by other element declarations, allowing for el
ement reuse.
Take a look at the following example.
Code Sample: SimpleTypes/Demos/AuthorGlobal.xsd
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="FirstName" type="xs:string"/>
<xs:element name="LastName" type="xs:string"/>
<xs:element name="Author">
<xs:complexType>
<xs:sequence>
<xs:element ref="FirstName"/>
<xs:element ref="LastName"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Code Explanation
In this example, the FirstName and LastName elements are both declared globally.
The global
elements are then referenced as children of the Author sequence.
Global vs. Local Simple-Type Elements
The major advantage of declaring an element globally is that the element can the
n be referenced
throughout the schema. This makes the code more modular and easier to maintain.
For example,
suppose that the song schema contained MusicWriter, LyricsWriter, and Singer ele
ments. Each of
these elements might have the child element Name. If the Name element is declare
d globally, any
changes to that element can be made in one location.
The major disadvantage of declaring elements globally is that all global element
s must have
unique names.
Code Sample: SimpleTypes/Demos/BookLocal.xsd
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:simpleType name="PersonTitle">
<xs:restriction base="xs:string">
<xs:enumeration value="Mr."/>
<xs:enumeration value="Ms."/>
<xs:enumeration value="Dr."/>
</xs:restriction>
</xs:simpleType>
<xs:element name="Book">
<xs:complexType>
<xs:sequence>
<xs:element name="Title" type="xs:string"/>
<xs:element name="Author">
<xs:complexType>
<xs:sequence>
<xs:element name="Title" type="PersonTitle"/>
<xs:element name="Name" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Code Explanation
Notice that there are two elements named Title, which can appear in different lo
cations in the
XML instance and are of different types. When the Title element appears at the r
oot of the XML
instance, its value can be any string; whereas, when it appears as a child of Au
thor, its value is
limited to "Mr.", "Ms.", or "Dr."
The example below defines a similar content model; however, because the elements
are declared
globally, the name Title cannot be used twice.
Code Sample: SimpleTypes/Demos/BookGlobal.xsd
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:simpleType name="PersonTitle">
<xs:restriction base="xs:string">
<xs:enumeration value="Mr."/>
<xs:enumeration value="Ms."/>
<xs:enumeration value="Dr."/>
</xs:restriction>
</xs:simpleType>
<xs:element name="BookTitle" type="xs:string"/>
<xs:element name="Title" type="PersonTitle"/>
<xs:element name="Name" type="xs:string"/>
<xs:element name="Book">
<xs:complexType>
<xs:sequence>
<xs:element ref="BookTitle"/>
<xs:element name="Author">
<xs:complexType>
<xs:sequence>
<xs:element ref="Title"/>
<xs:element ref="Name"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Exercise: Converting Simple-Type Element Declarations
from Local to Global
Duration: 10 to 20 minutes.
In this exercise, you will convert the element declarations in the song schema f
rom local to
global.
1. Open SimpleTypes/Exercises/Song3.xsd and save it as Song4.xsd in the sam
e directory.
2. Change the Title, Year, Artist, and Length elements to be declared globa
lly.
3. Try to validate SimpleTypes/Exercises/StrawberryFields.xml against the s
chema you just
created. If the XML document is invalid, fix your schema.
Where is the solution?
Default Values
Elements that do not have any children can have default values. To specify a def
ault value, use
the default attribute of the xs:element element.
Code Sample: SimpleTypes/Demos/EmployeeDefault.xsd
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
---- Code Omitted ----
<xs:element name="Employee">
<xs:complexType>
<xs:sequence>
<xs:element name="Salary" type="Salary"/>
<xs:element name="Title" type="JobTitle" default="Salesperson"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Code Explanation
When defaults are set in the XML schema, the following rules apply for the insta
nce document.
1. If the element appears in the document with content, the default value i
s ignored.
2. If the element appears without content, the default value is applied.
3. If the element does not appear, the element is left out. In other words,
providing a default
value does not imply that the element should be inserted if the XML instance aut
hor leaves it
out.
Examine the following XML instance. The Title element cannot be empty; it requir
es one of the
values from the enumeration defined in the JobTitle simple type. However, in acc
ordance with
number 2 above, the schema processor applies the default value of Salesperson to
the Title
element, so the instance validates successfully.
Code Sample: SimpleTypes/Demos/MikeSmith.xml
<?xml version="1.0"?>
<Employee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="EmployeeDefault.xsd">
<Salary>90000</Salary>
<Title/>
</Employee>
Fixed Values
Element values can be fixed, meaning that, if they appear in the instance docume
nt, they must
contain a specified value. Fixed elements are often used for boolean switches.
Code Sample: SimpleTypes/Demos/EmployeeFixed.xsd
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:simpleType name="Salary">
<xs:restriction base="xs:decimal">
<xs:minInclusive value="10000"/>
<xs:maxInclusive value="90000"/>
<xs:fractionDigits value="2"/>
<xs:totalDigits value="7"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="JobTitle">
<xs:restriction base="xs:string">
<xs:enumeration value="Sales Manager"/>
<xs:enumeration value="Salesperson"/>
<xs:enumeration value="Receptionist"/>
<xs:enumeration value="Developer"/>
</xs:restriction>
</xs:simpleType>
<xs:element name="Employee">
<xs:complexType>
<xs:sequence>
<xs:element name="Salary" type="Salary"/>
<xs:element name="Title" type="JobTitle"/>
<xs:element name="Status" type="xs:string" fixed="current"
minOccurs="0"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Code Explanation
The MinOccurs attribute is used to make the Status element optional. However, if
it is used, it
must contain the value current or be left empty, in which case, the value curren
t is implied. The
file SimpleTypes/Demos/LauraSmith.xml in the Demos folder validates against this
schema.
Nil Values
When an optional element is left out of an XML instance, it has no clear meaning
. For example,
suppose a schema declares a Name element as having required FirstName and LastNa
me
elements and an optional MiddleName element. And suppose a particular instance o
f this schema
does not include the MiddleName element. Does this mean that the instance author
did not know
the middle name of the person in question or does it mean the person in question
has no middle
name?
Setting the nillable attribute of xs:element to true indicates that such element
s can be set to nil by
setting the xsi:nil attribute to true.
Code Sample: SimpleTypes/Demos/AuthorNillable.xsd
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Author">
<xs:complexType>
<xs:sequence>
<xs:element name="FirstName" type="xs:string"/>
<xs:element name="MiddleName" type="xs:string" nillable="true"/>
<xs:element name="LastName" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Code Sample: SimpleTypes/Demos/MarkTwain.xml
<?xml version="1.0"?>
<Author xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="AuthorNillable.xsd">
<FirstName>Mark</FirstName>
<MiddleName xsi:nil="true"/>
<LastName>Twain</LastName>
</Author>
Code Explanation
By including the MiddleName element and setting xsi:nil to true, we are explicit
ly stating that
Mark Twain has no middle name.
Simple-Type Elements Conclusion
In this lesson of the XML tutorial, you have learned to work with XML Schema's b
uilt-in simple
types, to derive your own simple types, and to declare simple-type elements. We
will now take a
look at complex-type elements.


























Complex-Type Elements
Complex-Type Elements
In this lesson of the XML tutorial, you will learn...
1. To declare complex-type elements.
2. To use content models.
3. To control cardinality (quantity of elements).
4. To declare elements of mixed types.
5. To define named complex types.
Overview
Complex-type elements have attributes, child elements, or some combination of th
e two. For
example, the Name and HomePage elements below are both complex-type elements.
Code Sample: ComplexTypes/Demos/ComplexType.xml
<?xml version="1.0"?>
<Person>
<Name>
<FirstName>Mark</FirstName>
<LastName>Twain</LastName>
</Name>
<HomePage URL="http://www.marktwain.com"/>
</Person>
As the diagram below shows, a complex-type element can be empty, contain simple
content such
as a string, or can contain complex content such as a sequence of elements.
Whereas it is not necessary to explicitly declare that a simple-type element is
a simple type, it is
necessary to specify that a complex-type element is a complex type. This is done
with the
xs:complexType element as shown below.
Syntax
<xs:element name="ElementName">
<xs:complexType>
<!--Content Model Goes Here-->
</xs:complexType>
</xs:element>
Content Models
Content models are used to indicate the structure and order in which child eleme
nts can appear
within their parent element. Content models are made up of model groups. The thr
ee types of
model groups are listed below.
1. xs:sequence - the elements must appear in the order specified.
2. xs:all - the elements must appear, but order is not important.
3. xs:choice - only one of the elements can appear.
xs:sequence
The following sample shows the syntax for declaring a complex-type element as a
sequence,
meaning that the elements must show up in the order they are declared.
Syntax
<xs:element name="ElementName">
<xs:complexType>
<xs:sequence>
<xs:element name="Child1" type="xs:string"/>
<xs:element name="Child2" type="xs:string"/>
<xs:element name="Child3" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
xs:all
The following sample shows the syntax for declaring a complex-type element as a
conjunction,
meaning that the elements can show up in any order.
Syntax
<xs:element name="ElementName">
<xs:complexType>
<xs:all>
<xs:element name="Child1" type="xs:string"/>
<xs:element name="Child2" type="xs:string"/>
<xs:element name="Child3" type="xs:string"/>
</xs:all>
</xs:complexType>
</xs:element>
xs:choice
The following sample shows the syntax for declaring a complex-type element as a
choice,
meaning that only one of the child elements may show up.
Syntax
<xs:element name="ElementName">
<xs:complexType>
<xs:choice>
<xs:element name="Child1" type="xs:string"/>
<xs:element name="Child2" type="xs:string"/>
<xs:element name="Child3" type="xs:string"/>
</xs:choice>
</xs:complexType>
</xs:element>
Complex Model Groups
In the examples above, the model groups are all made up of simple-type elements.
However,
complex-type elements can contain other complex-type elements.
Syntax
<xs:element name="ElementName">
<xs:complexType>
<xs:choice>
<xs:element name="Child1" type="xs:string"/>
<xs:element name="Child2">
<xs:complexType>
<xs:sequence>
<xs:element name="GC1" type="xs:string"/>
<xs:element name="GC2" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="Child3" type="xs:string"/>
</xs:choice>
</xs:complexType>
</xs:element>
Furthermore, model groups can be nested within each other. The following example
illustrates
this. Notice that the choice model group, which allows for either a Salary eleme
nt or a Wage
element is nested with in a sequence model group. Both of the subsequent instanc
es are valid
according to this schema.
Code Sample: ComplexTypes/Demos/Employee.xsd
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:simpleType name="Salary">
<xs:restriction base="xs:decimal">
<xs:minInclusive value="10000"/>
<xs:maxInclusive value="90000"/>
</xs:restriction>
</xs:simpleType>
<xs:element name="Employee">
<xs:complexType>
<xs:sequence>
<xs:element name="Name">
<xs:complexType>
<xs:sequence>
<xs:element name="FirstName"/>
<xs:element name="LastName"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:choice>
<xs:element name="Salary" type="Salary"/>
<xs:element name="Wage" type="xs:decimal"/>
</xs:choice>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Code Sample: ComplexTypes/Demos/DaveSmith.xml
<?xml version="1.0"?>
<Employee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="Employee.xsd">
<Name>
<FirstName>Dave</FirstName>
<LastName>Smith</LastName>
</Name>
<Salary>90000</Salary>
</Employee>
Code Sample: ComplexTypes/Demos/JillSmith.xml
<?xml version="1.0"?>
<Employee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="Employee.xsd">
<Name>
<FirstName>Jill</FirstName>
<LastName>Smith</LastName>
</Name>
<Wage>20.50</Wage>
</Employee>
Occurrence Constraints
By default, elements that are declared locally must show up once and only once w
ithin their
parent. This constraint can be changed using the minOccurs and maxOccurs attribu
tes. The
default value of each of these attributes is 1. The value of minOccurs can be an
y non-negative
integer. The value of maxOccurs can be any positive integer or unbounded, meanin
g that the
element can appear an infinite number of times.
The example below shows how minOccurs can be used to make an element optional an
d how
maxOccurs can be used to allow an element to be repeated indefinitely.
Code Sample: ComplexTypes/Demos/Employee2.xsd
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:simpleType name="Salary">
<xs:restriction base="xs:decimal">
<xs:minInclusive value="10000"/>
<xs:maxInclusive value="90000"/>
</xs:restriction>
</xs:simpleType>
<xs:element name="Employee">
<xs:complexType>
<xs:sequence>
<xs:element name="Name">
<xs:complexType>
<xs:sequence>
<xs:element name="FirstName"/>
<xs:element name="MiddleName" minOccurs="0"/>
<xs:element name="LastName"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:choice>
<xs:element name="Salary" type="Salary"/>
<xs:element name="Wage" type="xs:decimal"/>
</xs:choice>
<xs:element name="Responsibilities">
<xs:complexType>
<xs:sequence>
<xs:element name="Responsibility" type="xs:string"
maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Code Explanation
Note that minOccurs and maxOccurs can also be applied to model groups (e.g, xs:s
equence) to
control the number of times a model group can be repeated.
Exercise: Adding ComplexType Elements
Duration: 15 to 25 minutes.
In this exercise, you will modify the song schema, adding model groups and occur
rence
constraints.
1. Open ComplexTypes/Exercises/Song.xsd for editing.
2. Modify the schema so that the Song element's children can appear in any
order.
3. Change the content model of the Song element so that it contains an Arti
sts element in
place of the Artist element.
4. Make the Artists element allow for one or more child Artist elements. No
te that the Artist
element is already declared globally.
5. Make the Length element optional.
6. Try to validate ComplexTypes/Exercises/WeAreTheWorld.xml against the sch
ema you
just created. If the XML document is invalid, fix your schema.
Where is the solution?
Declaring Global Complex-Type Elements
As with simple-type elements, complex-type elements can be declared globally by
placing the
element declaration as a child of the xs:schema element.
Globally declared elements cannot take occurrence constraints. However, the minO
ccurs and
maxOccurs constraints can be applied to references to globally declared elements
. To illustrate,
look at the following example. Notice that all elements, both simple-type and co
mplex-type, are
declared globally and then referenced within the model groups. Some of the refer
ences (e.g,
Responsibilities) have occurrence constraints assigned to them.
Code Sample: ComplexTypes/Demos/Employee3.xsd
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:simpleType name="Salary">
<xs:restriction base="xs:decimal">
<xs:minInclusive value="10000"/>
<xs:maxInclusive value="90000"/>
</xs:restriction>
</xs:simpleType>
<xs:element name="Name">
<xs:complexType>
<xs:sequence>
<xs:element ref="FirstName"/>
<xs:element ref="MiddleName" minOccurs="0"/>
<xs:element ref="LastName"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="FirstName"/>
<xs:element name="MiddleName"/>
<xs:element name="LastName"/>
<xs:element name="Wage" type="xs:decimal"/>
<xs:element name="Salary" type="Salary"/>
<xs:element name="Responsibilities">
<xs:complexType>
<xs:sequence>
<xs:element ref="Responsibility" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="Responsibility" type="xs:string"/>
<xs:element name="Employee">
<xs:complexType>
<xs:sequence>
<xs:element ref="Name"/>
<xs:choice>
<xs:element ref="Salary"/>
<xs:element ref="Wage"/>
</xs:choice>
<xs:element ref="Responsibilities" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Exercise: Converting Complex-Type Elements from Local to
Global
Duration: 10 to 15 minutes.
In this exercise, you will convert the Artists element declaration in the song s
chema from local to
global.
1. Open ComplexTypes/Exercises/Song.xsd and save it as Song2.xsd in the sam
e directory.
2. Change the Artists element to be declared globally.
3. Try to validate ComplexTypes/Exercises/TheGirlIsMine.xml against the sch
ema you just
created. If the XML document is invalid, fix your schema.
Where is the solution?
Mixed Content
Sometimes an element will contain both child elements and character text. For ex
ample, a para
element might contain mostly plain character text, but it could also have other
elements (e.g,
emphasis) littered throughout the character text.
As an example, let's examine look at the following XML instance document.
Code Sample: ComplexTypes/Demos/PaulMcCartney.xml
<?xml version="1.0"?>
<Employee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="Employee4.xsd">
<Name>
<FirstName>Paul</FirstName>
<LastName>McCartney</LastName>
</Name>
<Salary>90000</Salary>
<Bio>
Worked for <Company>the Beatles</Company> as a
<JobTitle>Singer</JobTitle>.
Worked for <Company>the Beatles</Company> as a
<JobTitle>Bass Guitarist</JobTitle>.
Worked for <Company>the Wings</Company> as a
<JobTitle>Singer</JobTitle>.
</Bio>
</Employee>
Code Explanation
Notice that the Bio element contains child elements Company and JobTitle as well
as character
text. Such elements are said to contain mixed content. The syntax for declaring
elements with
mixed content is shown below.
Syntax
<xs:element name="ElementName">
<xs:complexType mixed="true">
<xs:sequence>
<xs:element name="Child1" type="xs:string"/>
<xs:element name="Child2" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
The following example illustrates how to define this in our employee schema.
Code Sample: ComplexTypes/Demos/Employee4.xsd
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
---- Code Omitted ----
<xs:element name="Bio">
<xs:complexType mixed="true">
<xs:sequence maxOccurs="unbounded">
<xs:element name="Company" type="xs:string"/>
<xs:element name="JobTitle" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
---- Code Omitted ----
</xs:schema>
Defining Complex Types Globally
As with simple types, complex types can be defined globally. The example below s
hows how this
is done.
Code Sample: ComplexTypes/Demos/Author.xsd
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:complexType name="Person">
<xs:sequence>
<xs:element name="FirstName" type="xs:string"/>
<xs:element name="LastName" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:element name="Author" type="Person"/>
</xs:schema>
Code Explanation
As you can see, complex types are defined with the xs:complexType element. The m
ajor
advantage of defining a complex type globally is that it can be reused. For exam
ple, a schema
might allow for an Illustrator element as well as an Author element. Both elemen
ts could be of
type Person. This way, if the Person type is changed later, the change will appl
y to both elements.
The instance document below will validate properly against the schema above.
Code Sample: ComplexTypes/Demos/MarkTwain.xml
<?xml version="1.0"?>
<Author xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="Author.xsd">
<FirstName>Mark</FirstName>
<LastName>Twain</LastName>
</Author>
Complex-Type Elements Conclusion
In this lesson of the XML tutorial, you have learned to work with complex types
and complex-
type elements. We will now take a look at declaring attributes.