First Compact Patterns
Let’s explore how the patterns described in the previous chapter translate into the compact syntax.
The text Pattern
text
is the simplest pattern in the XML syntax and
is the simplest in the compact syntax as well. The
text
pattern is just:
text
In this definition, the word text
identifies the
text pattern.
Of course, because both syntaxes are equivalent, all
that’s been said about text
in
RELAX NG’s XML syntax also applies to
text
in the compact syntax.
The attribute Pattern
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.
Because empty curly brackets ({}
) look weird and
might imply empty attributes rather than attributes containing a text
value, the convention of the XML syntax that 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, the following:
<attribute name="id"/>
translates into:
attribute id { text }
while this:
attribute id { }
translates into a syntax error.
The compact
syntax is position-sensitive, and words such as
text
and attribute
are reserved
words only when they appear in the first position. This is very
convenient when you need to define attributes (or elements) that have
names that are the same as reserved words. For instance, you can
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
isn’t confused when reserved words are used as
attribute names. This is also true for the element
pattern
which you’ll see in the
next section.
Element
The simplest definition of the name
element is:
element name { text }
To add an attribute to an element, you need a delimiter between the different pieces of content. You’ll see more use of delimiters and their meanings in Chapter 6, but for now, let’s use a comma as delimiter between content. This has the same effect as with XML syntax:
element title { attribute xml:lang { text }, text }
Whitespace (i.e., spaces, tabulations, line feeds, and carriage returns) isn’t 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 whitespace so that there is only one definition per line. This technique, 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 treats both as equivalent.
The author
element can be defined using more of
the same components:
element author { attribute id { text }, element name { text }, element born { text }, element died { text } }
Again, all that I’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.
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 the attribute id
as
optional, you’d write:
attribute id { text }?
Note that the qualifier ?
must be added after the
definition of the pattern but before the delimiter. If you used this
qualifier in the larger definition of the author
element, it’d therefore look like this:
element author { attribute id { text }, element name { text }, element born { text }?, element died { text }? }
In Chapter 3, I mentioned that other combinations
of optional and required elements can 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 you need a container if you
wish to create the same combinations. The container is a a set of
parentheses ()
. The effect of parentheses depends
on the optional qualifier following them. Parentheses without a
qualifier are effectively transparent; they do nothing. The
definition of author
can be written as:
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. Parentheses are more useful (and are actually required) to write the combinations mentioned in Chapter 3. Combinations such as:
<optional> <element name="born"> <text/> </element> <element name="died"> <text/> </element> </optional>
translate into:
(element born { text }, element died { text })?
The following:
<optional> <element name="born"> <text/> </element> <optional> <element name="died"> <text/> </element> </optional> </optional>
translates into:
(element born { text }, element died { text }? )?
Get RELAX NG now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.