CIT041X Index > Relax NG (Compact Syntax)

First Steps

Let's take a very simple grammar: an address book consists of zero or more cards, each of which consists of a name and email address. Here's the specification in the compact form of RNG. In these notes, when we refer to a block, this means a series of Relax NG specifications enclosed in curly braces { and }.

We begin with a grammar block that encloses the entire specification. The start = keywords tells a validator where to start validating; i.e., which element is the root element. The rest is a pattern that tells what a valid document should look like. Relax NG works by specifying a pattern for structure and content of valid documents. Any document that matches the pattern is valid; any document that doesn’t, isn’t. If you’ve read the tutorial, you’ll notice that the first examples don’t have the grammar and start specifications. They aren’t necessary for a “self-contained” example like this one, but as soon as we start specifying more complex grammars, we’ll need them. So why not now?

grammar
{
    start = element addressBook
    {
        element card
        {
            element name {text},
            element email {text}
        }*
    }
}

If you want to require at least one <card> element, replace the * with +. An optional element is followed by a ? (just as in Unix regular expressions). So, if we want a card to be able to contain an optional <note> element, we’d have this specification (the added material is in boldface):

grammar
{
    start = element addressBook
    {
        element card
        {
            element name {text},
            element email {text},
            element note {text}?
        }*
    }
}

Choices and Groups

Let’s say that we can contact someone either by email or by phone number (but not both). We’d modify our specification this way, showing only the relevant portion. The | character is used to specify a choice. If there is any possibility of ambiguity, you must use parentheses to show which elements are involved in the choice.

element card
{
    element name {text},
    (
        element email {text} |
        element phone {text}
    ),
    element note {text}?
}*

Now let’s say that we can either have a name (for example, a company name) or a first name/last name pair. Using parentheses lets us say it easily:

element card
{
    (
        element name {text} |
        (
            element firstname {text},
            element lastname {text}
        )
    ),

    (element email {text} |
    element phone {text}),
    element note {text}?
}*