[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: XML Schemas: Best Practices
- From: "Roger L. Costello" <costello@mitre.org>
- To: xml-dev@lists.xml.org
- Date: Tue, 08 May 2001 08:11:33 -0500
Subject: Implementing variable content containers using
"dangling types".
Problem: Suppose that we have an element, sensor, which contains
the name of a weather station sensor. For example:
<sensor>Barometric Pressure</sensor>
Several things to note:
1. This element holds a simpleType.
2. Each weather station may have sensors
that are unique to it. Consequently,
we must design our schema so that the sensor
element can be customized by each weather
station.
Motivation for the Below Solution:
In previous discussions we have examined ways to
create variable content containers:
1. Abstract element combined with element
substitution.
2. Use a <choice> element.
3. Abstract type and type substitution.
These are excellent methods - if the content is
complex. However, if the content is a simpleType
then these methods are not applicable!
So, we need a new method - one that allows us to
create simpleType variable content containers.
Solution: Here's the solution - when you create sensor, declare
it to be of a type from another namespace. Then, for
the <import> element don't provide a schemaLocation.
Thus, the element is declared to be of a type
for which no particular schema is identified,
i.e., we have a dangling type definition!
Let me explain. In your schema, declare the
sensor element:
<xsd:element name="sensor" type="s:sensor_type"/>
Note that I declared the sensor element to have
a type "sensor_type", which is in a different
namespace - the sensor namespace:
xmlns:s="http://www.sensor.org"
Now here's the key - when you <import> this
namespace, don't provide a value for schemaLocation!
For example:
<xsd:import namespace="http://www.sensor.org"/>
The instance document must then identify a schema
that defines sensor_type. Thus, at run time
we are matching up the reference to sensor_type
with the implementation of sensor_type. Wow!
For example:
xsi:schemaLocation=
"http://www.weather-station.org weather-station.xsd
http://www.sensor.org boston-sensors.xsd"
[In an instance document] schemaLocation is
identifying a schema, boston-sensors.xsd,
which provides an implementation of sensor_type.
Example: Let's look at the complete schemas and instance
documents.
First, let's look at weather-station.xsd. This schema
declares a sensor element which references a type in
another namespace:
weather-station.xsd
----------------------------------------------------------
<?xml version="1.0"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2000/10/XMLSchema"
targetNamespace="http://www.weather-station.org"
xmlns="http://www.weather-station.org"
xmlns:s="http://www.sensor.org"
elementFormDefault="qualified">
<xsd:import namespace="http://www.sensor.org"/>
<xsd:element name="weather-station">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="sensor" type="s:sensor_type"
maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
----------------------------------------------------------
Note that the <import> element does not have a schemaLocation
attribute to identify a particular schema which implements
sensor_type. The schema validator will resolve this
reference to sensor_type based upon collection of schemas
that is provided in the instance document.
The Boston weather station creates a schema which defines
sensor_type:
boston-sensors.xsd
----------------------------------------------------------
<?xml version="1.0"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2000/10/XMLSchema"
targetNamespace="http://www.sensor.org"
xmlns="http://www.sensor.org"
elementFormDefault="qualified">
<xsd:simpleType name="sensor_type">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="barometer"/>
<xsd:enumeration value="thermometer"/>
<xsd:enumeration value="anenometer"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:schema>
----------------------------------------------------------
Now an instance document can conform to weather-station.xsd
and use boston-sensors.xsd as the implementation of sensor_type:
boston-weather-station.xml
----------------------------------------------------------
<?xml version="1.0"?>
<weather-station xmlns="http://www.weather-station.org"
xmlns:xsi="http://www.w3.org/2000/10/XMLSchema-instance"
xsi:schemaLocation=
"http://www.weather-station.org weather-station.xsd
http://www.sensor.org boston-sensors.xsd">
<sensor>thermometer</sensor>
<sensor>barometer</sensor>
<sensor>anenometer</sensor>
</weather-station>
----------------------------------------------------------
Suppose that the London weather station has all the sensors
that Boston has, plus some additional ones unique to the London
weather patterns. Thus, London will create its own implementation
of sensor_type:
london-sensors.xsd
----------------------------------------------------------
<?xml version="1.0"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2000/10/XMLSchema"
targetNamespace="http://www.sensor.org"
xmlns="http://www.sensor.org"
elementFormDefault="qualified">
<xsd:simpleType name="sensor_type">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="barometer"/>
<xsd:enumeration value="thermometer"/>
<xsd:enumeration value="anenometer"/>
<xsd:enumeration value="hygrometer"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:schema>
----------------------------------------------------------
Note that this schema has an additional sensor_type
that Boston does not have - hygrometer.
The London weather station instance document will be
a collection of weather-station.xsd and london-sensors.xsd:
london-weather-station.xml
----------------------------------------------------------
<?xml version="1.0"?>
<weather-station xmlns="http://www.weather-station.org"
xmlns:xsi="http://www.w3.org/2000/10/XMLSchema-instance"
xsi:schemaLocation=
"http://www.weather-station.org weather-station.xsd
http://www.sensor.org london-sensors.xsd">
<sensor>thermometer</sensor>
<sensor>barometer</sensor>
<sensor>hygrometer</sensor>
<sensor>anenometer</sensor>
</weather-station>
----------------------------------------------------------
Summary: The key to this design pattern is:
1. When you declare the variable content container
element give it a type that is in another
namespace, e.g., s:sensor_type
2. When you <import> that namespace don't provide
a value for schemaLocation, e.g.,
<xsd:import namespace="http://www.sensors.org"/>
3. Create any number of implementations of the type:
- boston-sensors.xsd
- london-sensors.xsd
4. In instance documents identify the schema that
shall be used to define the type, e.g.,
xsi:schemaLocation=
"http://www.weather-station.org weather-station.xsd
----> http://www.sensor.org london-sensors.xsd"
Note: The implementation of sensor_type does not have
to be a simpleType. A schema could define it as a complexType.
This is a really exciting and powerful design pattern! I
am very excited about this. Do you have any thoughts or
comments? /Roger