Relax NG Compact

Relax NG Compact is a compact, non-XML syntax equivalent to Relax NG. The name of a Relax NG Compact document ends with ".rnc".

Basic Semantics

The following example illustrates the basic semantics of Relax NG Compact.

<?xml version="1.0" ?>
<emailsList>
   <person id="232133">
      <firstName>Adam</firstName>
      <lastName>Khoo</lastName>
      <email>adamkhoo@yahoo.com</email>
      <sex>M</sex>
      <scores>88 97</scores>
      <description>
         This is a <b>smart guy</b>.
      </description>
      <VIP/>
   </person>
   <person>
      <id>234023</id>
      <name>Serena</name>
      <email>serena@yahoo.com</email>
      <sex>  F  </sex>
      <scores>50 78.5</scores>
   </person>
</emailsList>

datatypes xs="http://www.w3.org/2001/XMLSchema-datatypes"
element emailsList {
   element person {
      (element id {xs:integer} |   # a comment
       attribute id {xs:integer}),
      (element name {text} |
       (element firstName {text} &
        element lastName {text})),
      element email {
         xsd:string {
            minLength="5"
            maxLength="125"}
         },
      element sex {string "M" | "F"},
      element scores {
         list {xsd:float, xsd:float}
      },
      element description{
         mixed {element b{text}}
      }?,
      element VIP {empty}?
   }*
}
* denotes zero or more.
+ denotes one or more.
? denotes zero or one.
() denotes grouping.
, denotes a sequence.
| denotes a choice.
& denotes interleaving (out-of-order sequence).
# denotes a comment.

'xsd' is a built-in datatypes library; its URI is "http://www.w3.org/2001/XMLSchema-datatypes".

The 'string' keyword before "M" means that there must be no spaces before or after "M".

The order of elements in a sequence (denoted by ,) is significant. The order of attributes in a sequence is not.

References

The following, rather complex, example demonstrates various ways to use references.

<?xml version="1.0"?>
<!-- badminton.xml -->
<badminton id="3432">
   <players.min>2</players.min>
   <players.max>4</players.max>
</badminton>

#badminton1.rnc
element badminton {
   external "badminton2.rnc"
}

#badminton2.rnc
grammar {
   include "badminton3.rnc" {
      idd = attribute id{text}
   }
   pNum &= element players.min {text}
   pNum &= idd
   start = pNum
}

#badminton3.rnc
grammar {
   pNum=element players.max {text}
   idd=element id {text}
}
'external' references another .rnc document as if the content of that document were in its current place.

'include' allows grammars to be merged. The optional {...} clause next to 'include' overrides the included definitions. The content designator, 'start', can be replaced likewise.

&= combines the definitions, interleaving them.
|= combines the definitions, joining them with |.

In a grammar definition, there can be recursive references within an element, e.g.:
inline = element span {inline | text}
To use keywords such as 'element', 'attribute', 'text', 'empty', or 'grammar' as the name of a definition, it must be prefixed with \, e.g.:
start = \element
\element = element element {text}
In a nested grammar, to use the definition from the parent, prefix the name with 'parent '.

'notAllowed' is typically used to allow an including pattern to specify additional choices with |=, e.g.:

grammar {
   inline = notAllowed       # inline.rnc
}

grammar {
   include "inline.rnc"
   inline |= element code {inline} | element em {inline}
}

Namespaces

The following example illustrates various ways to use namespaces.

<?xml version="1.0"?>
<book xmlns="http://example2.com">
   <title xmlns="http://example1.com">
      Web Coding Bible
   </title>
   <genre xmlns="http://example1.com">
      Manual
   </genre>
</book>

#book.rnc
namespace a = "http://example1.com"
default namespace = "http://example2.com"
element book {
   element a:title {text},
   external "book2.rnc" inherit = a
}

#book2.rnc
namespace c = inherit
element c:genre {text}
Unless 'inherit'ed explicitly, a namespace declaration applies only to the file in which it appears. A file referenced using 'include' or 'external' cannot take advantage of the namespace declarations of the referencing file.

A default namespace does not apply to attributes. The attribute name in an attribute declaration must be prefixed with the namespace prefix if desired.
default namespace eg = "http://example.com"

is equivalent to declaring both a default namespace and a prefixed namespace for the same URI:

default namespace = "http://example.com"
namespace eg = "http://example.com"
In the book.rnc example above, 'inherit = a' can be omitted if the default namespace is to be inherited instead.

Wildcards

* can be used to denote any element or any attribute.

<?xml version="1.0"?>
<house id="100">
   <type>bungalow</type>
   <cost xmlns="http://example.com">500000</cost>
   <area>10000</area>
</house>

namespace a = "http://example.com"
element house {
   attribute * {text}+,      #any attribute
   element * {text},         #any element
   element (a:*|*) {text}, #union of namespaces
   element * - a:* {text}  #difference
}

Annotations and String Literals

The following example shows how to use annotations.

namespace an = "http://example.com"
grammar {
   [an:dummy = "elements"]
   div {
      a = element a {text}
      an:entity [name="picture"]
      b = element b {text}
   }
   [an:dummy = "attributes"]
   div {
      c = attribute c {text}
      d = attribute d {text}
   }
   start = a
}
## This is the documentation syntax.
element a {text}

is equivalent to:

namespace d = "http://relaxng.org/ns/compatibility/annotations/1.0"
[d:documentation ["This is documentation syntax."]]
element a {text}
"Line 1\x{A}" ~ "Line 2"

is equivalent to both of the following (string literals can be delimited by triple quotes):

'''Line 1
Line 2'''
"""Line 1
Line 2"""

\x{A} denotes an escaped newline, and ~ denotes concatenation.