OASIS Mailing List ArchivesView the OASIS mailing list archive below
or browse/search using MarkMail.

 


Help: OASIS Mailing Lists Help | MarkMail Help

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: XML Schemas: Best Practices



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