RELAX NG by Eric van der Vlist will be published by O'Reilly & Associates (ISBN: 0596004214)

You are welcome to use our annotation system to give your feedback.


Declaring Namespaces in Schemas

Namespace declarations in a RELAX NG schema follow the same principles as namespace declarations in an instance document with some small differences in the syntax. RELAX NG supports the use of both the default namespace and prefixes.

The namespace on which a schema expects to operate in the instance document can be defined through the ns attribute. Like the datatypeLibrary attribute seen earlier, ns is an inherited attribute. Being inherited means that we can define it in the document element of the schema if it remains the same all over the schema. For instance, to write a schema for the the first example in this chapter, where the entire library is using the same namespace, we could write:

 <?xml version="1.0" encoding="utf-8"?>
 <element xmlns="http://relaxng.org/ns/structure/1.0" name="library"
          ns="http://eric.van-der-vlist.com/ns/library">
  <oneOrMore>
   <element name="book">
    <attribute name="id"/>
    .../...
   </element>
  </oneOrMore>
 </element>

The compact syntax uses a slightly different declaration, default namespace, at the top of the schema:

 default namespace = "http://eric.van-der-vlist.com/ns/library"
      
 element library
 {
    element book
    {
       attribute id { text },
       .../...
       }*
    }+
 }
[Note]Note

The definition of the default namespace in a RELAX NG schema does not apply to attributes. This works precisely as the default namespace doesn't apply to attributes in instance documents, and should cause a minimum of surprises.

Just as default namespaces could be used and changed all over a multi-namespace document, when we are using the XML syntax the "ns" attribute can be changed in a schema. To validate the documents with the two namespaces shown in our "10 minute guide to namespaces", we could write:

 <?xml version="1.0" encoding="utf-8"?>
 <element xmlns="http://relaxng.org/ns/structure/1.0"
  name="library"
  ns="http://eric.van-der-vlist.com/ns/library">
  <oneOrMore>
   <element name="book">
    <attribute name="id"/>
    <attribute name="available"/>
    <element name="isbn">
     <text/>
    </element>
    <element name="title">
     <attribute name="xml:lang"/>
     <text/>
    </element>
    <zeroOrMore>
     <element name="author" ns="http://eric.van-der-vlist.com/ns/person">
      <attribute name="id"/>
      <element name="name">
       <text/>
      </element>
      <element name="born">
       <text/>
      </element>
      <optional>
       <element name="dead">
        <text/>
       </element>
      </optional>
     </element>
    </zeroOrMore>
    <zeroOrMore>
     <element name="character">
      <attribute name="id"/>
      <element name="name" ns="http://eric.van-der-vlist.com/ns/person">
       <text/>
      </element>
      <element name="born" ns="http://eric.van-der-vlist.com/ns/person">
       <text/>
      </element>
      <element name="qualification">
       <text/>
      </element>
     </element>
    </zeroOrMore>
   </element>
  </oneOrMore>
 </element>
[Note]Note

The compact syntax does not provide a way to redefine the default namespace. Defining prefixes is the preferred way to define schemas with multiple namespaces when using the compact syntax.

Since the three variations used to write the document with the two namespaces in our "10 minute guide" are considered equivalent to namespace-aware applications, the schema which we've just written will validate all of them. There is thus complete independence between the prefixes and default namespaces used to write the instance document, and those used in the schema. Namespace matching only tests the namespace URIs of each element and attribute, not the prefixes.

The definition of the default target namespace in RELAX NG is done through an "ns" attribute, and thus does not rely on the declaration of the default namespace of the RELAX NG document itself. (In our examples, the default namespace of the RELAX NG document is the RELAX NG namespace.) The declaration of the prefixes used for target namespaces other than the default is done through namespace declarations like those used in instance documents. In other words, to define an hr prefix, which will be used as a prefix for the namespaces in names or attributes of the instance, I use an "xmlns:hr" declaration as if I wanted to use it as a prefix for an element or attribute of the RELAX NG document.

We can mix both default and non-default namespaces in our schemas and write:

 <?xml version="1.0" encoding="utf-8"?>
 <element xmlns="http://relaxng.org/ns/structure/1.0"
  name="library"
  ns="http://eric.van-der-vlist.com/ns/library"
  xmlns:hr="http://eric.van-der-vlist.com/ns/person">
  <!-- The default target namespace is "http://eric.van-der-vlist.com/ns/library" -->
  <oneOrMore>
   <element name="book">
    <attribute name="id"/>
    <attribute name="available"/>
    <element name="isbn">
     <text/>
    </element>
    <element name="title">
     <attribute name="xml:lang"/>
     <text/>
    </element>
    <zeroOrMore>
     <element name="hr:author">
     <!-- Here we are using a "hr" prefix to match "http://eric.van-der-vlist.com/ns/person"
-->
      <attribute name="id"/>
      <element name="hr:name">
       <text/>
      </element>
      <element name="hr:born">
       <text/>
      </element>
      <optional>
       <element name="hr:dead">
        <text/>
       </element>
      </optional>
     </element>
    </zeroOrMore>
    <zeroOrMore>
     <element name="character">
      <attribute name="id"/>
      <element name="hr:name">
       <text/>
      </element>
      <element name="hr:born">
       <text/>
      </element>
      <element name="qualification">
       <text/>
      </element>
     </element>
    </zeroOrMore>
   </element>
  </oneOrMore>
 </element>

The compact syntax uses its own declaration to define namespace prefixes:

 default namespace = "http://eric.van-der-vlist.com/ns/library"
 namespace hr = "http://eric.van-der-vlist.com/ns/person"
      
 element library
 {
    element book
    {
       attribute id { text },
       attribute available { text },
       element isbn { text },
       element title { attribute xml:lang { text }, text },
       element hr:author
       {
          attribute id { text },
          element hr:name { text },
          element hr:born { text },
          element hr:dead { text }?
       }*,
       element character
       {
          attribute id { text },
          element hr:name { text },
          element hr:born { text },
          element qualification { text }
       }*
    }+
 }

Again, this schema will validate the three variations seen in the "10 minute guide". In fact, this schema validates exactly the same set of documents as the schema using only default namespaces. A third equivalent variation uses prefixes for both namespaces:

 <?xml version="1.0" encoding="utf-8"?>
 <element xmlns="http://relaxng.org/ns/structure/1.0"
  name="lib:library"
  xmlns:lib="http://eric.van-der-vlist.com/ns/library"
  xmlns:hr="http://eric.van-der-vlist.com/ns/person">
  <oneOrMore>
   <element name="lib:book">
    <attribute name="id"/>
    <attribute name="available"/>
    <element name="lib:isbn">
     <text/>
    </element>
    <element name="lib:title">
     <attribute name="xml:lang"/>
     <text/>
    </element>
    <zeroOrMore>
     <element name="hr:author">
      <attribute name="id"/>
      <element name="hr:name">
       <text/>
      </element>
      <element name="hr:born">
       <text/>
      </element>
      <optional>
       <element name="hr:dead">
        <text/>
       </element>
      </optional>
     </element>
    </zeroOrMore>
    <zeroOrMore>
     <element name="lib:character">
      <attribute name="id"/>
      <element name="hr:name">
       <text/>
      </element>
      <element name="hr:born">
       <text/>
      </element>
      <element name="lib:qualification">
       <text/>
      </element>
     </element>
    </zeroOrMore>
   </element>
  </oneOrMore>
 </element>

or:

 namespace lib = "http://eric.van-der-vlist.com/ns/library"
 namespace hr = "http://eric.van-der-vlist.com/ns/person"
      
 element lib:library
 {
    element lib:book
    {
       attribute id { text },
       attribute available { text },
       element lib:isbn { text },
       element lib:title { attribute xml:lang { text }, text },
       element hr:author
       {
          attribute id { text },
          element hr:name { text },
          element hr:born { text },
          element hr:dead { text }?
       }*,
       element lib:character
       {
          attribute id { text },
          element hr:name { text },
          element hr:born { text },
          element lib:qualification { text }
       }*
    }+
 }

Again, this schema is equivalent to the previous ones since it validates all the variations of namespaces declarations in the instance documents.


You are welcome to use our annotation system to give your feedback.
[Annotations for this page]
All text is copyright Eric van der Vlist, Dyomedea. During development, I give permission for non-commercial copying for educational and review purposes. After publication, all text will be released under the Free Software Foundation GFDL.