10.10. Chameleon Design
When we initially introduced these features, we didn't worry about namespaces. However, these features have some important interactions with namespaces, since W3C XML Schema restricts inclusion (or redefinition) to pieces of schema with either the same target namespace or without any target namespace (schemas for other languages being "imported" rather than "included").
When a piece of schema that has no target namespace is included in a schema with a target namespace, the included definition acquires the target namespace of the including schema and behaves exactly as if it added the same target namespace. This feature allows creation of libraries with pieces of schema that are "namespace-transparent," and which take the namespace of the schema in which they are imported. This method is often called "chameleon," since the included schema takes the "color" of the context in which it is included.
To illustrate this feature and see its implication, let's look again at the example that we've used throughout this chapter:
<?xml version="1.0"?> <library xmlns="http://dyomedea.com/ns/library"> <book id="b0836217462"> <title> Being a Dog Is a Full-Time Job </title> <authors> <person id="CMS"> <name> Charles M Schulz </name> </person> </authors> </book> </library>
If we want a library of schema parts that describe a person and can be included within several vocabularies, we can include a piece of schema that has no target namespace. This piece of schema would be something like the following (note that we do not define any target namespace):
<?xml version="1.0"?> <xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:element name="person"> <xs:complexType> <xs:sequence> <xs:element name="name" type="xs:string"/> </xs:sequence> <xs:attribute name="id" type="xs:string" use="required"/> </xs:complexType> </xs:element> </xs:schema>
And the including schema would look similar to the following example:
<?xml version="1.0"?> <xs:schema targetNamespace="http://dyomedea.com/ns/library" elementFormDefault="qualified" xmlns="http://dyomedea.com/ns/library" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:include schemaLocation="very-simple-1-ns-ppl.xsd"/> <xs:element name="library"> <xs:complexType> <xs:sequence> <xs:element name="book"> <xs:complexType> <xs:sequence> <xs:element name="title" type="xs:string"/> <xs:element name="authors"> <xs:complexType> <xs:sequence> <xs:element ref="person"/> </xs:sequence> </xs:complexType> </xs:element> </xs:sequence> <xs:attribute name="id" type="xs:ID"/> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> </xs:element> </xs:schema>
While this looks very easy and neat, we may wonder if we are really building something modular. Including a piece of schema is similar to including a C header file. While this is slightly better than a copy/paste, the level of modularity that can be achieved in this way is very restricted.
The namespace of the element person is the namespace given to our library. An application cannot guess from looking at the instance document that this element is the same as a person element that it will find in another document describing, for example, an employee.
Looking at the modified infoset and checking the datatype doesn't help either, since the datatype will be defined as a datatype from a schema with the target namespace of our library, and won't match other target namespaces, including the same piece of schema.
The fact that the same person element is used by different vocabularies is totally lost by the processing of the include (or redefine). Before using it, you may consider if it isn't more useful to include information in the instance document using a separate namespace, or at least include information in the modified infoset by importing datatypes from another namespace rather than including common definitions.
Copyright © 2002 O'Reilly & Associates. All rights reserved.