by Eric van der Vlist is published by O'Reilly & Associates (ISBN: 0596004214)
RELAX not only lets you create building blocks for inclusion into schemas, it lets you create generic building blocks that take on a namespace you specify when including those blocks into your own schemas. These generic blocks, called chameleon schemas, are designed so that they can take on the namespace of their surrounding environment.
Chapter 10 explored the schemas for XHTML 2.0. At the time, I told you not to worry about the namespace declarations because they hadn't been introduced yet. It's time to take a closer look at XHTML's namespace usage. XHTML's namespace declarations in the top level schema, the driver schema, are present only in the grammar element:
<?xml version="1.0" encoding="UTF-8"?> <grammar ns="http://www.w3.org/2002/06/xhtml2" xmlns="http://relaxng.org/ns/structure/1.0" xmlns:x="http://www.w3.org/1999/xhtml"> <x:h1>RELAX NG schema for XHTML 2.0</x:h1> .../... <x:h3>Structure Module</x:h3> <include href="xhtml-struct-2.rng"/> .../... </grammar> |
What does this snippet demonstrate?
Means that the default namespace of the schema as a XML document is http://relaxng.org/ns/structure/1.0. Translated, it means that elements without prefix in the schema as a XML document are RELAX NG patterns.
Defines the default namespace for the schema itself: the schema describes elements from the http://www.w3.org/2002/06/xhtml2 namespace unless some other namespace is explicitly defined. Let's call it the "target namespace" to avoid any confusion with the default namespace of the schema considered as a XML document.
Means that the prefix x is assigned to http://www.w3.org/1999/xhtml. This declaration is used here to include XHTML documentation in the schema. This approach will be explored in more detail in Chapter 13.
In the compact syntax, this looks like:
default namespace = "http://www.w3.org/2002/06/xhtml2" namespace x = "http://www.w3.org/1999/xhtml" .../... include "xhtml-struct-2.rnc" |
Let's now have a look at the module describing the structure:
<?xml version="1.0" encoding="UTF-8"?> <grammar xmlns="http://relaxng.org/ns/structure/1.0" xmlns:x="http://www.w3.org/1999/xhtml"> <x:h1>Structure Module</x:h1> .../... </grammar> |
or:
namespace x = "http://www.w3.org/1999/xhtml" x:h1 "Structure Module" start = html ... |
The big difference from the top-level schema is that the target namespace isn't defined at all in the schema defining the module.
How can that work? It's a feature common to the include and externalRef patterns. When no target namespace is defined in the imported schema, the target namespace from the schema performing the inclusion or containing the external reference is used. In our case, this means that the target namespace from the driver (http://www.w3.org/2002/06/xhtml2) is used by any module that doesn't specify a target namespace.
Schemas without a target namespace are often called chameleon schemas because they take on the target namespace of any context in which they are included or referenced.
In the compact syntax, an inherit qualifier has been added to specify that a namespace must be inherited at inclusion or external reference time:
namespace xhtml2 = "http://www.w3.org/2002/06/xhtml2" namespace x = "http://www.w3.org/1999/xhtml" .../... include "xhtml-struct-2.rnc" inherit = xhtml2 |
This inherit qualifier plays the same role as an ns attribute in an include or externalRef of the XML syntax.
Moving from XHTML to the library, it may be a good idea to incorporate XHTML elements into the description of our library. This could, for instance, allow the same content for the definition of titles and qualification that's used in the XHTML p element, i.e., what's described in the "Inline text" module as the Inline.model named pattern. The idea behind the module mechanism is that you can select just you we need. Let's do that by including the common modules (xhtml-attribs-2.rng and xhtml-datatypes-2.rng) and the "Inline Text" module (xhtml-inltext-2.rng):
<?xml version="1.0" encoding="UTF-8"?> <grammar xmlns="http://relaxng.org/ns/structure/1.0"> <start> <ref name="library"/> </start> <include href="xhtml-attribs-2.rng"/> <include href="xhtml-inltext-2.rng"/> <include href="xhtml-datatypes-2.rng"/> <define name="library"> <element name="library"> <oneOrMore> <element name="book"> <attribute name="id"/> <attribute name="available"/> <element name="isbn"> <text/> </element> <element name="title"> <attribute name="xml:lang"/> <ref name="Inline.model"/> </element> <oneOrMore> <element name="author"> <attribute name="id"/> <element name="name"> <text/> </element> <optional> <element name="born"> <text/> </element> </optional> <optional> <element name="died"> <text/> </element> </optional> </element> </oneOrMore> <zeroOrMore> <element name="character"> <attribute name="id"/> <element name="name"> <text/> </element> <optional> <element name="born"> <text/> </element> </optional> <element name="qualification"> <ref name="Inline.model"/> </element> </element> </zeroOrMore> </element> </oneOrMore> </element> </define> </grammar> |
or:
start = library include "xhtml-attribs-2.rnc" include "xhtml-inltext-2.rnc" include "xhtml-datatypes-2.rnc" library = element library { element book { attribute id { text }, attribute available { text }, element isbn { text }, element title { attribute xml:lang { text }, Inline.model }, element author { attribute id { text }, element name { text }, element born { text }?, element died { text }? }+, element character { attribute id { text }, element name { text }, element born { text }?, element qualification { Inline.model } }* }+ } |
With this schema, I can include all the XHTML formatting described in the "Inline Text Module" in my title and qualification elements, but they must be in the target namespace defined in this schema (i.e., with no namespace because I haven't defined a target namespace here). The local names of the elements are thus the same as those of XHTML 2.0, but these elements are in no namespace. Here's an example of a valid document:
<?xml version="1.0" encoding="utf-8"?> <library> <book id="b0836217462" available="true"> <isbn>0836217462</isbn> <title xml:lang="en">Being a Dog Is a <em>Full-Time Job</em></title> <author id="CMS"> <name>Charles M Schulz</name> <born>1922-11-26</born> <died>2000-02-12</died> </author> <character id="PP"> <name>Peppermint Patty</name> <born>1966-08-22</born> <qualification>bold, brash and tomboyish</qualification> </character>"http://www.w3.org/2002/06/xhtml2" <character id="Snoopy"> <name>Snoopy</name> <born>1950-10-04</born> <qualification>extroverted <strong>beagle</strong></qualification> </character> <character id="Schroeder"> <name>Schroeder</name> <born>1951-05-30</born> <qualification>brought classical music to the Peanuts strip</qualification> </character> <character id="Lucy"> <name>Lucy</name> <born>1952-03-03</born> <qualification>bossy, crabby and selfish</qualification> </character> </book> </library> |
Because the XHTML 2.0 schemas for the modules are chameleon schemas, importing the definitions from XHTML in the XHTML 2.0 namespace requires specifying the namespace in the include patterns:
<?xml version="1.0" encoding="UTF-8"?> <grammar xmlns="http://relaxng.org/ns/structure/1.0"> <start> <ref name="library"/> </start> <include href="xhtml-attribs-2.rng" ns="http://www.w3.org/2002/06/xhtml2"/> <include href="xhtml-inltext-2.rng" ns="http://www.w3.org/2002/06/xhtml2"/> <include href="xhtml-datatypes-2.rng" ns="http://www.w3.org/2002/06/xhtml2"/> <define name="library"> <element name="library"> <oneOrMore> <element name="book"> <attribute name="id"/> <attribute name="available"/> <element name="isbn"> <text/>which </element> <element name="title"> <attribute name="xml:lang"/> <ref name="Inline.model"/> </element> <oneOrMore> <element name="author"> <attribute name="id"/> <element name="name"> <text/> </element> <optional> <element name="born"> <text/> </element> </optional> <optional> <element name="died"> <text/> </element> </optional> </element> </oneOrMore> <zeroOrMore> <element name="character"> <attribute name="id"/> <element name="name"> <text/> </element> <optional> <element name="born"> <text/> </element> </optional> <element name="qualification"> <ref name="Inline.model"/> </element> </element> </zeroOrMore> </element> </oneOrMore> </element> </define> </grammar> |
or:
namespace x = "http://www.w3.org/2002/06/xhtml2" start = library include "xhtml-attribs-2.rnc" inherit = x include "xhtml-inltext-2.rnc" inherit = x include "xhtml-datatypes-2.rnc" inherit = x library = element library { element book { attribute id { text }, attribute available { text }, element isbn { text }, element title { attribute xml:lang { text }, Inline.model }, element author { attribute id { text }, element name { text }, element born { text }?, element died { text }? }+, element character { attribute id { text }, element name { text }, element born { text }?, element qualification { Inline.model } }* }+ } |
The namespace that's inherited is now explicitly set to http://www.w3.org/2002/06/xhtml2. Valid documents look like:
<?xml version="1.0" encoding="utf-8"?> <library xmlns:x="http://www.w3.org/2002/06/xhtml2"> <book id="b0836217462" available="true"> <isbn>0836217462</isbn> <title xml:lang="en">Being a Dog Is a <x:em>Full-Time Job</x:em></title> <author id="CMS"> <name>Charles M Schulz</name> <born>1922-11-26</born> <died>2000-02-12</died> </author> <character id="PP"> <name>Peppermint Patty</name> <born>1966-08-22</born> <qualification>bold, brash and tomboyish</qualification> </character> <character id="Snoopy"> <name>Snoopy</name> <born>1950-10-04</born> <qualification>extroverted <x:strong>beagle</x:strong></qualification> </character> <character id="Schroeder"> <name>Schroeder</name> <born>1951-05-30</born> <qualification>brought classical music to the Peanuts strip</qualification> </character> <character id="Lucy"> <name>Lucy</name> <born>1952-03-03</born> <qualification>bossy, crabby and selfish</qualification> </character> </book> </library> |
Chameleon schemas are very controversial. On the bright side, they can be very handy for some kinds of vocabularies. The first variation of XHTML inclusion in our library is more concise than the second, which required the declaration of the XHTML namespace in each document and a prefix on XHTML elements. On the other hand, you can question the benefit of adding XHTML elements if they can't be identified as XHTML by their namespace. Yes, you can add em or strong elements to title and qualification elements, but how can an application recognize them as XHTML components if they have no namespace, or belong to the namespace of your own application?
Chameleon schemas work contrary to most developers' namespace expectations, and in the process remove most of the value of using namespaces. For this reason I would recommend you be very cautious when using them!
This text is released under the Free Software Foundation GFDL.