Relax NG

Relax NG (REgular LAnguage for XML Next Generation) is XML-based. It is somewhat simpler to learn than XSD. The name of a Relax NG file ends with ".rng".

Basic Features

The following example illustrates the basic features of Relax NG.

<?xml version="1.0"?>
<zoo>
   <animal id="l123444" id2="L234423">
      <name>Mighty</name>
      <type>lion</type>
      <kg>135</kg>
      <imported/>
   </animal>
   <animal id="b355345">
      <name>Lucky</name>
      <type>bear</type>
      <kg>205</kg>
   </animal>
</zoo>

<?xml version="1.0"?>
<element name="zoo"
               xmlns="http://relaxng.org/ns/structure/1.0">
   <zeroOrMore>
      <element name="animal">
         <attribute name="id"/>
         <element name="name"><text/></element>
         <element name="type"><text/></element>
         <element name="kg"><text/></element>
         <optional>
            <element name="imported"><empty/></element>
            <attribute name="id2"/>
         </optional>
      </element>
   </zeroOrMore>
</element>
oneOrMore can be used in place of zeroOrMore, if at least one child element must be present.

Relax NG does not allow <element> to be empty; the following is invalid: <element name="x"/>.

The order of elements is significant, but the order of attributes is not.

Choice, Group, and Data

The following example illustrates the use of <choice>, <group>, and <data>.

<?xml version="1.0"?>
<personalDetails>
   <person>
      <name>Ali</name>
      <sex>m</sex>
   </person>
   <person sex="f">
      <firstName>Sharon</firstName>
      <lastName>Ann</lastName>
   </person>
</personalDetails>

<?xml version="1.0"?>
<element name="personalDetails"
               xmlns="http://relaxng.org/ns/structure/1.0">
   <zeroOrMore>
      <element name="person">
         <choice>
            <element name="name"><text/></element>
            <group>
               <element name="firstName"><text/></element>
               <element name="lastName"><text/></element>
            </group>
         </choice>
         <choice>
            <element name="sex">
               <data type="string"
                     datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
                  <param name="maxLength">1</param>
               </data>
            </element>
            <attribute name="sex">
               <choice>
                  <value>m</value>
                  <value>f</value>
               </choice>
            </attribute>
         </choice>
      </element>
   </zeroOrMore>
</element>
The 'datatypeLibrary' attribute can appear on any ancestor element instead.

List, Interleave, and Mixed

The following example illustrates the use of <list>, <interleave>, and <mixed>.

<?xml version="1.0"?>
<data>
   <myList1>SN 4432 1234 3287 ZZ</myList1>
   <myList2><b/><c/><a/></myList2>
   <myList3>as324<a/>23423<b/>4sd</myList3>
</data>

<?xml version="1.0"?>
<element
    name="data"
    xmlns="http://relaxng.org/ns/structure/1.0"
    datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
   <element name="myList1">
      <list>
         <data type="string"/>
         <oneOrMore>
            <data type="int"/>
         </oneOrMore>
         <optional>
            <data type="string"/>
         </optional>
      </list>
   </element>
   <element name="myList2">
      <interleave>
         <element name="a"><empty/></element>
         <element name="b"><empty/></element>
         <optional>
            <element name="c"><empty/></element>
         </optional>
      </interleave>
   </element>
   <element name="myList3">
      <mixed>
         <element name="a"><empty/></element>
         <element name="b"><empty/></element>
      </mixed>
   </element>
</element>
Combining attributes with <interleave> has the same effect as combining them with <group>.

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>

<?xml version="1.0"?>
<!-- badminton1.rng -->
<element
   name="badminton"
   xmlns="http://relaxng.org/ns/structure/1.0">
   <externalRef href="badminton2.rng"/>
</element>

<?xml version="1.0"?>
<!-- badminton2.rng -->
<grammar xmlns="http://relaxng.org/ns/structure/1.0">
   <include href="badminton3.rng">
      <define name="idd">
         <attribute name="id"/>
      </define>
   </include>
   <define name="pNum" combine="interleave">
      <element name="players.min">
         <text/>
      </element>
      <ref name="idd"/>
   </define>
   <start>
      <ref name="pNum"/>
   </start>
</grammar>

<?xml version="1.0"?>
<!-- badminton3.rng -->
<grammar xmlns="http://relaxng.org/ns/structure/1.0">
   <define name="pNum">
      <element name="players.max">
         <text/>
      </element>
   </define>
   <define name="idd">
      <element name="id">
         <text/>
      </element>
   </define>
</grammar>
Theoretically, the three schema files could be merged into one; they appear as separate files here to illustrate <externalRef> and <include>. The <include> element, if not empty, contains definitions that override the included definitions.

The 'combine' attribute can take other values, such as 'choice'.

In a grammar definition, there can be recursive references within an <element>.

If a nested <grammar> is used, parentRef can be used in place of ref to escape out of the current grammar and reference a definition from the parent.

<notAllowed/> never matches anything. It can be used with combine="choice" to allow the including pattern to specify additional choices.

Namespaces

A namespace can be declared for an element or an attribute with the 'ns' attribute.

<?xml version="1.0"?>
<xn1:section id="199"
         xmlns:xn1="http://example1.com"
         xmlns:xn2="http://example2.com">
   <xn1:subsection1/>
   <xn2:subsection2/>
</xn1:section>

<?xml version="1.0"?>
<element name="section"
               xmlns="http://relaxng.org/ns/structure/1.0"
               xmlns:myNS="http://example2.com"
               ns="http://example1.com">
 <element name="subsection1"><empty/></element>
 <element name="myNS:subsection2"><empty/></element>
 <attribute name="id"/>
</element>
<element> inherits the value of the 'ns' attribute of the nearest ancestor, but <attribute> does not. The XML document would be invalid if xn1:id="199" were used instead, because the id attribute is declared to have the empty (or absent) namespace.

Here, <element name="myNS:subsection2"> is equivalent to:
<element name="subsection2" ns="http://example2.com">

anyName and nsName

The following example allows an element to have any attribute with a qualified name, but if an 'xml:space' attribute is present, it must have the value 'default' or 'preserve'.

<?xml version="1.0"?>
<element
   name="example"
   xmlns="http://relaxng.org/ns/structure/1.0">
   <zeroOrMore>
      <attribute>
         <anyName>
            <except>
               <name>xml:space</name>
            </except>
         </anyName>
      </attribute>
   </zeroOrMore>
   <optional>
      <attribute name="xml:space">
         <choice>
            <value>default</value>
            <value>preserve</value>
         </choice>
      </attribute>
   </optional>
</element>
Instead of <name>, <nsName> can be used to match any name with the namespace URI specified by the 'ns' attribute:
<element>
  <anyName>
    <except>
      <nsName/>
      <nsName ns=""/>
    </except>
  </anyName>
</element>

This matches any namespace-qualified element, provided it is qualified with a namespace other than that of the parent element.

(Courtesy of http://relaxng.org/tutorial-20011203.html#IDAFLZR)

Annotations

Annotations can be attached anywhere. <div> allows an annotation to be applied to a group of definitions in a <grammar>.

<?xml version="1.0"?>
<grammar xmlns:m="http://www.example.com/module">
   <m:documentation>Here are the animals.
   </m:documentation>
   <div m:name="These are reptiles.">
      <define name="crocodile">
         <attribute name="crocodile"/></define>
      <define name="snake">
         <attribute name="snake"/></define>
      <define name="alligator">
         <attribute name="alligator"/></define>
   </div>
   <div m:name="These are mammals.">
      <define name="dog">
         <attribute name="dog"/></define>
      <define name="cat">
         <attribute name="cat"/></define>
      <define name="tiger">
         <attribute name="tiger"/></define>
   </div>
</grammar>