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.
Let's explore how the patterns described in the previous chapter translate into the compact syntax.
text was the simplest pattern in the XML syntax and is the simplest in the compact syntax as well. 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 in RELAX NG's XML syntax also applies to text in the compact syntax.
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 id is the name of the attribute. The curly brackets {...} delimit the definition of the content of the attribute.
Since empty curly brackets ({ }) look weird and might imply empty attributes rather than attributes containing a text value, the convention of the XML syntax which makes a text pattern the implicit content for attributes is abandoned in the compact syntax. The content of attributes must be explicitly defined when you're using the compact syntax. In other words, in the compact system,
<attribute name="id"/> |
translates into
attribute id { text } |
while
attribute id { } |
translates into a syntax error.
The compact syntax is position-sensitive and words such as text and attribute are only reserved words when they appear in the first position. This is very convenient when we need to define attributes (or elements) that have names that 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.
The simplest definition of the name element would be:
element name { text } |
To add an attribute to an element, we need a delimiter between the different pieces of content. We'll see more use of delimiters and their meanings in Chapter 6: More Patterns, but for now, we'll use a comma (,) as delimiter between content. This will have the same effect we've seen with XML syntax:
element title { attribute xml:lang { text }, text } |
White space (i.e. spaces, tabulations, line feeds and carriage return) is not significant for the compact syntax. The previous bit of code could also have been written:
element title {attribute xml:lang{ text }, text} |
Many people tend to prefer to split up their code with white space so that there is only one definition per line. The first form, with each line helping to guide a reader through the structure, is more human-readable, but a RELAX NG processor won't have any problems understanding the content. It will treat both as equivalent.
The author element can defined using more of the same components 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
The optional pattern is formalized as a trailing ? added after a definition, as is true in DTDs as well. For example, to define that the attribute id is optional we would write:
attribute id { text }? |
Note that the qualifier ? must be added after the definition of the pattern but before the delimiter. If we used this in the larger definition of our author element, it would therefore look like this:
element author { attribute id { text }, element name { text }, element born { text }?, element died { text }? } |
In Chapter 3, we mentioned that other combinations of what is optional and what is not could be described using the optional pattern as a container. In the compact syntax, the optional pattern is represented as a qualifier rather than a container, so we need a container if we need to create the same combinations. The container is the parenthesis (...). The effect of parentheses depends on the optional qualifier following them. Parentheses without a qualifier are effectively transparent; they do nothing. 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. Combinations like: |
<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 into:
(element born { text }, element died { text }? )? |
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 }? }+ |
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.