[XML-DEV Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message] 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
|
PURCHASE STYLUS STUDIO ONLINE TODAY!Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced! Download The World's Best XML IDE!Accelerate XML development with our award-winning XML IDE - Download a free trial today! Subscribe in XML format
|