by Eric van der Vlist is published by O'Reilly & Associates (ISBN: 0596004214)


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.

Using the Default Namespace

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 you can define it in the document element of the schema (and never again) if it remains the same throughout the schema. For instance, to write a schema for the first example in this chapter, in which the entire library is using the same namespace, I can 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 },
       ...
      }*
   }+
}
[Tip]Tip

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

Just as default namespaces can be used and changed all over a multinamespace document, when using the XML syntax, the ns attribute can be changed in a schema. To validate the documents with the two namespaces shown in Section 11.1, I can 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>
[Tip]Tip

The compact syntax doesn't 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.

Because the three variations used to write the document with the two namespaces in Section 11.1 are considered equivalent to namespace-aware applications, the schema 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 tests only the namespace URIs of each element and attribute, not the prefixes.

Using Prefixes

The definition of the default target namespace in RELAX NG is done through an ns attribute, and thus doesn't 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 is 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.

You can mix both default and nondefault namespaces 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 validates the three variations seen in Section 11.1. 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 because it validates all the variations of namespaces declarations in the instance documents.


This text is released under the Free Software Foundation GFDL.