There
are four schools of thought on the schema design patterns. These are the
Russian Doll, the Salami Slice, the Venetian Blind and the Garden of Eden
approach.
The main characteristic that differentiates these approaches are
whether the elements and types are globally defined. Elements and types
that are global are direct children of the <schema> node.
Elements and types are considered local when they are nested within other
elements and types. If elements or types are global then they are
available for reuse by other schemas using either import or include
statements. Locally defined elements and types are not available for
reuse.
In
the Russian Doll approach,
the schema has one single global element - the root element. All other
elements and types are nested progressively deeper giving it the name due to
each type fitting into the one above it. Since the elements in this
design are declared locally they will not be reusable through the import or
include statements. This will not change if the elements are namespace
qualified or namespace unqualified.
<?xml
version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:element name="BookInformation">
<xs:complexType>
<xs:sequence>
<xs:element name="Title"/>
<xs:element name="ISBN"/>
<xs:element name="PeopleInvolved">
<xs:complexType>
<xs:sequence>
<xs:element name="Author"/>
<xs:element name="Publisher">
<xs:complexType>
<xs:sequence>
<xs:element name="CompanyName"/>
<xs:element name="ContactPerson"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:element name="BookInformation">
<xs:complexType>
<xs:sequence>
<xs:element name="Title"/>
<xs:element name="ISBN"/>
<xs:element name="PeopleInvolved">
<xs:complexType>
<xs:sequence>
<xs:element name="Author"/>
<xs:element name="Publisher">
<xs:complexType>
<xs:sequence>
<xs:element name="CompanyName"/>
<xs:element name="ContactPerson"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
The advantages of the Russian Doll approach are: The
schema is self contained as it has all of its parts in the schema and does not
interact with other schemas. In as much as it is self contained it is
also decoupled. Since the content of the schema is not visible to other
schemas, changes to the schema are decoupled from other schema components.
The disadvantage is that it is not reusable.
This type of approach would be appropriate for use within a
single application or for migration of data from legacy systems.
In
the Salami Slice approach all elements are defined
globally but the type definitions are defined locally. This way other
schemas may reuse the elements. With this approach, a global element with
its locally defined type provide a complete description of the elements
content. This information 'slice' is declared individually and then
aggregated back together and may also be pieced together to construct other
schemas.
<?xml
version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:element name="BookInformation">
<xs:complexType>
<xs:sequence>
<xs:element ref="Title"/>
<xs:element ref="ISBN"/>
<xs:element ref="PeopleInvolved">
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="Title"/>
<xs:element name="ISBN"/>
<xs:element name="PeopleInvolved">
<xs:complexType>
<xs:sequence>
<xs:element ref="Author"/>
<xs:element ref="Publisher"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="Author"/>
<xs:element name="Publisher">
</xs:schema>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:element name="BookInformation">
<xs:complexType>
<xs:sequence>
<xs:element ref="Title"/>
<xs:element ref="ISBN"/>
<xs:element ref="PeopleInvolved">
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="Title"/>
<xs:element name="ISBN"/>
<xs:element name="PeopleInvolved">
<xs:complexType>
<xs:sequence>
<xs:element ref="Author"/>
<xs:element ref="Publisher"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="Author"/>
<xs:element name="Publisher">
</xs:schema>
The advantage is that the schema is reusable since the elements
are declared globally.
The disadvantages are: the schema is verbose since each element
is declared globally and then referenced to describe the data which leads to
larger schema size. This approach also is not self contained and is
coupled. The elements defined may be contained in other schemas and
because of this the schema is coupled to other schema and thus changes to one
schema will impact other schemas.
This type of approach is commonly used since it is easy to
understand and create reusable components. It would be an appropriate
design to promote reusability and data standardization across differing
applications. This approach is not, however, recommended when
modifications to the standard elements will be necessary. If the length,
data types, restrictions or other modifications of the elements need to be
changed then this will cause added work as well as a larger impact to other
systems.
The Venetian Blind approach is similar to the Russian
Doll approach in that they both use a single global element. The Venetian
Blind approach describes a modular approach by naming and defining all type
definitions globally (as opposed to the Salami Slice approach which declares
elements globally and types locally). Each globally defined type
describes an individual "slat" and can be reused by other
components. In addition, all the locally declared elements can be
namespace qualified or namespace unqualified (the slats can be
"opened" or "closed") depending on the elementFormDefault
attribute setting at the top of the schema. If the namespace is
unqualified then the local elements in the instance document must not be
qualified with the prefix of the namespace.
<?xml
version="1.0" encoding="UTF-8"?>
<xs:schema targetNamespace="TargetNamespace" xmlns:TN="TargetNamespace" xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:element name="BookInformation" type="TN:BookInformation" maxOccurs="unbounded"/>
<xs:complexType name="BookInformation">
<xs:sequence>
<xs:element name="Title"/>
<xs:element name="ISBN"/>
<xs:element name="PeopleInvolved" type="TN:PeopleInvolvedType" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="PeopleInvolvedType">
<xs:sequence>
<xs:element name="Author"/>
<xs:element name="Publisher"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
<xs:schema targetNamespace="TargetNamespace" xmlns:TN="TargetNamespace" xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:element name="BookInformation" type="TN:BookInformation" maxOccurs="unbounded"/>
<xs:complexType name="BookInformation">
<xs:sequence>
<xs:element name="Title"/>
<xs:element name="ISBN"/>
<xs:element name="PeopleInvolved" type="TN:PeopleInvolvedType" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="PeopleInvolvedType">
<xs:sequence>
<xs:element name="Author"/>
<xs:element name="Publisher"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
The advantages are that since all complex and simple types are
defined globally they are available for reuse. In addition, the option
exists to hide the namespace prefix for all locally defined elements in the
instance document.
The disadvantages are that the schema is verbose, it is not self
contained and it may be coupled with other schemas.
This type of approach is good when flexibility, reuse and
namespace exposure are important. This approach uses a combination of
local and global types unlike the Russian Doll approach which all components
are locally declared and the Salami Slice where all components are globally
declared. This is important as it provides the flexibility to create a
schema for most needs since the types can be assigned to elements and extended
or restricted as needed. This would be an appropriate design when data is
transferred between diverse organizations or business units since it provides each
group the flexibility for modifications for each specific requirement.
The Garden of Eden approach implements characteristics of
the Venetian Blind and Salami Slice approach. Like the Salami Slice the
Garden of Eden uses a modular approach by defining all elements globally and
like the Venetian Blind approach all type definitions are declared
globally. Each element is globally defined as an immediate child of the <schema>
node and its type attribute can be set to one of the named complex types.
Since the elements are globally declared, the namespace must be exposed no
matter what the settings of the elementFormDefault attribute is.
Therefore, if the elementFormDefault attribute is set to qualified, this does
not change the content and structure of the instance document but if the
attribute is set to unqualified then the local elements in the instance
document must not be qualified with the prefix of the namespace prefix.
<?xml
version="1.0" encoding="UTF-8"?>
<xs:schema targetNamespace="TargetNamespace" xmlns:TN="TargetNamespace" xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:element name="BookInformation" type="BookInformationType"/>
<xs:complexType name="BookInformationType">
<xs:sequence>
<xs:element ref="Title"/>
<xs:element ref="ISBN"/>
<xs:element ref="Publisher"/>
<xs:element ref="PeopleInvolved" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="PeopleInvolvedType">
<xs:sequence>
<xs:element name="Author"/>
</xs:sequence>
</xs:complexType>
<xs:element name="Title"/>
<xs:element name="ISBN"/>
<xs:element name="Publisher"/>
<xs:element name="PeopleInvolved" type="PeopleInvolvedType"/>
</xs:schema>
<xs:schema targetNamespace="TargetNamespace" xmlns:TN="TargetNamespace" xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:element name="BookInformation" type="BookInformationType"/>
<xs:complexType name="BookInformationType">
<xs:sequence>
<xs:element ref="Title"/>
<xs:element ref="ISBN"/>
<xs:element ref="Publisher"/>
<xs:element ref="PeopleInvolved" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="PeopleInvolvedType">
<xs:sequence>
<xs:element name="Author"/>
</xs:sequence>
</xs:complexType>
<xs:element name="Title"/>
<xs:element name="ISBN"/>
<xs:element name="Publisher"/>
<xs:element name="PeopleInvolved" type="PeopleInvolvedType"/>
</xs:schema>
The advantage of this approach is that the schemas are
reusable. Since both the elements and types are defined globally both are
available for reuse. This approach offers the maximum amount of reusable
content.
The disadvantages are the that the schema is verbose.
Since everything is globally declared and then referenced the size of the
schema is increased. Also, the schema is not self contained and can be
coupled with other schemas thus possibly affecting other schemas with any
changes made. Lastly, there is no option to hide the namespace since they
are always exposed on globally defined items.
This type of approach is good when need the flexibility of both
global elements and global types. This is also a good approach when you
need to allow other schema authors to extend or restrict your types or you want
to allow them to compose custom types by picking constituent types from your
schema. This would be an appropriate design when you are creating general
libraries in which you can afford to make no assumptions about the scope of the
schema elements and types and their use in other schemas particularly in
reference to extensibility and modularity.