!!!Getting started

Although the schema shown in the previous chapter was simple, its XML representation was rather verbose. This is not surprising nor even uncommon for XML vocabularies. In fact it even conforms quite well to the basic principles of XML, a Recommendation whose design goals state that "XML documents should be human-legible and reasonably clear" but also "Terseness in XML markup is of minimal importance". Our schema is a good example of a document which is "human-legible and reasonably clear" and... verbose!

The principal goal of the XML syntax is to be a serialization of Relax NG schemas which is easily processable by computers using a standard XML toolkit and James Clark has introduced a second syntax, strictly equivalent to the XML syntax, which is both more concise and easier for humans to read and write. Relax NG processors are free to support this "compact" syntax or not; if a Relax NG processor doesn't users can use existing translators to translate the XML syntax to and from the compact syntax. Since these two forms are strictly equivalent, there is no loss of information during translation and even comments and the annotations which will be presented in "Chapter 13: Annotating Schemas" are preserved in the process. This is, of course, not true of the "syntactical details" of XML such as entity expansion or Processing Instructions which are lost when the XML syntax is translated into compact but this is a limitation of the XML processing architecture rather than a limitation of Relax NG itself.

The compact syntax has been published as official OASIS Relax NG committee specification but not yes submitted as to the ISO.

We'll see that this syntax is a strange mix between concepts borrowed from the definition of structures in programming languages, some notations from XML DTDs and the Relax NG patterns which, of course, we'll find there: element and attribute patterns look like Java declarations with their curly brackets preceded by a reserved word ("element" or "attribute") which is their Relax NG pattern name. On the other hand, optional, one or more and zero or more are represented by DTD qualifier suffixes ("?" for optional, "+" for one or more and "*" for zero or more). But don't worry, the result is incredibly good and intuitive and you'll find this syntax both simple and familiar before the end of this book!

!!!Our first compact patterns

Let's see how our first patterns translate into the compact syntax.

!!text

This was the simplest pattern in the XML syntax and this is still the simplest with the compact syntax! The "text" pattern is just... "text":

 text

In this definition, the word "text" identifies the text pattern.

And of course, since both syntaxes are equivalent, all we've said about "<text/>" is true for "text".

!!attribute

For the compact syntax, the "attribute" pattern borrows Java's curly brackets:

 attribute id { text }

In this definition, the first word "attribute" identifies the "attribute" pattern, the second one "available" is the name of the attribute (we will see in "Chapter 12: Writing Extensible Schemas" how this could be extended to define sets of names) and the curly brackets "{...}" delimit the definition of the content of the attribute.

Since empty curly brackets "{}" would have looked weird and would have kind of imply "empty" attributes rather than attributes containing a text value, the convention of the XML syntax making a "text" pattern an implicit content for attributes has not been carried on to the compact syntax. The definition of the content of attributes is thus mandatory and must be explicitly made when you're using the compact syntax. In other word,

  <attribute name="id"/>

translates into:

 attribute id { text }

and

 attribute id { }

is just a syntax error for the compact syntax.

The compact syntax is position sensitive and words such as "text" and "attribute" are reserved words only when they appear in first position. In practice, this is very convenient when we need to define attributes (or elements) which name are reserved words. For instance, I could define attributes named "text" or even "attribute" without any precaution such as:

 attribute text { text }
 attribute attribute { text }

Because the compact syntax is position sensitive, it wouldn't be confused by the fact that I have used reserved words as attribute names. This would be the same for the "element" pattern which we'll see in the next section.

!!Element

You'll have already guessed that the definition of the name element would be:

 element name { text }

To add an attribute to our elements we need a delimiter between the different content within a single element. We'll see more delimiters and their meaning in "Chapter 6: More Patterns" and for the moment we'll use a comma (",") as delimiter between content and this will have the same effect than what we've seen with the XML syntax:

    element title {
      attribute xml:lang { text },
      text
    }

White spaces (i.e. spaces, tabulations, line feeds and carriage return) are not significant for the compact syntax and this could have been written:

    element title {attribute xml:lang { text }, text}

As with programming languages, many people tend to prefer to split definitions so that there is only one per line and tend to consider the first form as more readable but a Relax NG processor won't get confused and will treat both as equivalent.

We can add more content and write our author element as:

    element author {
      attribute id { text },
      element name { text },
      element born { text },
      element died { text }
    }

Again, all what we've said about the properties of the "element" pattern in the XML syntax is true for the compact syntax: these are just two equivalent syntaxes for the same pattern.

To meet our requirements, we need to introduce the "optional" pattern

!!optional

Here is where DTDs have been asked to contribute! The optional pattern is formalized as a trailing "?" added after a definition. To define that the attribute "id" is optional we would write:

 attribute id { text }?

and to define that the "born" element is optional we write:

 element born { text }?

Note that this qualifier ("?") must be added after the definition of the pattern but before the delimiter. The definition of our author element would thus be:

    element author {
      attribute id { text },
      element name { text },
      element born { text }?,
      element died { text }?
    }

In "Chapter 3: First Schema", we had mentioned that other combinations could be described using the "optional" pattern as a container. In the compact syntax, the "optional" pattern is a qualifier and we need a container to define the same combinations. This container are the parenthesis "(...)". They are neutral in that their effect depends on the delimiter used within the parenthesis and on the optional qualifier following them. The definition of our author could be written:

    element author {(
      attribute id { text },
      element name { text },
      element born { text }?,
      element died { text }?
    )}

or

    element author {
      (attribute id { text }),
      (element name { text }),
      (element born { text })?,
      (element died { text }?)
    }

 without changing its meaning at all. They are more useful (and actually even required) to write the combinations mentioned in the previous chapter and:

 <optional>
  <element name="born">
   <text/>
  </element>
  <element name="died">
   <text/>
  </element>
 </optional>

would translate as:

      (element born { text }, element died { text })?

While

 <optional>
  <element name="born">
   <text/>
  </element>
  <optional>
   <element name="died">
    <text/>
   </element>
  </optional>
 </optional>

Would translate as:

      (element born { text }, element died { text }? )?


!!oneOrMore

The oneOrMore pattern is also a qualifier and, in the DTD tradition it is a "+":

    element author {
      attribute id { text },
      element name { text },
      element born { text }?,
      element died { text }?
    }+

!!zeroOrMore

Last but not least, the "zeroOrMore" pattern is the "*" qualifier:


    element character {
      attribute id { text },
      element name { text },
      element born { text }?,
      element qualification { text }
    }*

!!!Full schema

 element library {
   element book {
     attribute id { text },
     attribute available { text },
     element isbn { text },
     element title {
       attribute xml:lang { text },
       text
     },
     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 { text }
     }*
   }+
 }


In the following chapters, for each example we will give both the XML and the compact syntax and we will have plenty of opportunities to get familiarized with both.

Note that there should be no confusion between the simple form of a Relax NG schema described in "Chapter 15: Simplification And Restrictions" and the compact syntax. These two notions are orthogonal and work at different level: the simple form is the result of simplifications internally done by Relax NG processors on the data model resulting from the parsing of a Relax NG "full" document; the compact syntax is another way to represent or serialize a Relax NG "full" document. The data models resulting from the parsing of a Relax NG full schema are thus the same if the schema has been written using the XML or the compact syntax and it will simplified into the same simple schema.

!!!XML or compact?

Let's take a look at both syntaxes side by side:

[http://localhost/rngbook/xml-comp.png]

There are two things which we immediately notice:

*The compact syntax is much more... compact.
*The XML syntax is... XML and plays fine with generic XML tools (here a web browser) while the compact syntax isn't XML and must be used with other tools (here the text editor VIM with a plug-in to highlight Relax NG's compact syntax).

These two findings summarize pretty well why they are both needed. The compact syntax is nice to work with and you'll probably find it soon more pleasant to edit your schemas and document your vocabularies. On the other hand, the XML syntax is wonderful if you want to either generate Relax NG schemas as we will see in "Chapter 14: Generating Relax NG schemas" or generate anything out of your Relax NG schemas using XML tools which will be covered in "Chapter 13: Annotating Schemas". And the fact that they can be translated without information loss is a guarantee that we can use both.
