Relax NG ist eine Beschreibungssprache für XML-Dokumente.
Nehmen wir eine Adresse:
<Vorname>...</Vorname>
<weitereVornamen>...</weitereVornamen>
<Nachname>...</Nachname>
<PLZ>...</PLZ>
<Ort>...</Ort>
Relax beschreibt dieses XML, indem es die Elemente aufführt:
<element name="Vorname"> <text/></element>
<optional>
<element name="weitereVornamen"> <text/></element>
</optional>
<element name="Nachname"> <text/></element>
<element name="PLZ">
<data type="Integer">
<param name="maxLength">5</param>
</data>
</element>
<element name="Ort"> <text/></element>
<text/> wurde z.B. bei der PLZ genauer spezifiziert, hier sollen 5 Ziffern stehen.
Eine genauere Eingrenzung der Ziffern kann über pattern
<param name="pattern">[1-9]{1}[0-9]{1}[0-9]{1}[0-9]{1}[0-9]{1}</param>
erfolgen. in unserem Beispiel darf die 1. Ziffer nie 0 werden.
Soll <text/> leer sein, muss hier <empty/> stehen.
Reihenfolge: Ohne eine Klammerung durch <interleave> ist die Reihenfolge der XML-Elemente einzuhalten.
Anzahl von Elementen im Block:
- <optional> (Element oder Attribut kann vorkommen, muss aber nicht)
- <zeroOrMore>
- <oneOrMore>
Attribute zu Elementen werden beschrieben durch:
<attribute name="Status">
<choice>
<value>verfuegbar</value>
<value>verkauft</value>
<value>bestellt</value>
</choice>
</attribute>
wobei <choice> eine Wertemenge definiert.
Mit <choice> kann auch eine Auswahl aus Elementen eingeleitet werden. Will man dabei erzwingen, dass mehrere Elemente zusammen genannt werden müssen, werden diese mit <group> geklammert.
<element name="Eintrag">
<choice>
<element name="Name">
<text/>
</element>
<group>
<element name="Vorname">
<text/>
</element>
<element name="Nachname">
<text/>
</element>
</group>
</choice>
<element name="email">
<text/>
</element>
</element>
Das XML kann dann so
<Eintrag><Name>Knut HansenHampel</Name><email>knut@hansenhampel.de</email></Eintrag>
oder so
<Eintrag><Vorname>Knut</Vorname><Nachname>HansenHampel</Nachname><email>otto@hansenhampel.de</email></Eintrag>
aussehen.
Blöcke: Wiederverwendbare Blöcke kann man mit <define name="meinBlock"> anlegen und mit <ref name="meinBlock"> inkludieren. Wenn man den Block in ein eigenes File auslagert, bindet man es mit <externalRef href="meinBlock.rng"/> ein.
<define name="meinBlock">
<element name="Name">
<text/>
</element>
<element name="Email">
<text/>
</element>
</define>
<grammar>: Will man mehrere Blöcke definieren und einbinden, dann beginnt man eine Grammatik mit <grammar><start> und einem oder mehreren Elementen, die sich mittels <ref auf die außerhalb von </start> definierten Pattern beziehen.
<grammar>
<start>
<zeroOrMore>
<element name="Eintrag">
<ref name="meinBlock"/>
</element>
</zeroOrMore>
</start>
<define name="meinBlock">
<element name="Name">
<text/>
</element>
<element name="Email">
<text/>
</element>
</define>
</grammar>
<include>: Grammatiken mit mehreren Blöcken aus <define name=...> können in eigene Files ausgelagert und mittels <include href="myGrammar.inc"/> zusammengeführt werden. Dabei wird nicht alles ein-zu-eins wie bei <externalRef inkludiert, sondern nur das, was sich innerhalb der <grammar>-Klammer befindet. (Wie bereits erwähnt, kann man auch abgeschlossene Grammatik-Blöcke auslagern; diese werden dann mit <externalRef href="meinBlock.rng"/> als Ganzes eingebunden.)
Wird die <include -Klammer nicht geschlossen und enthält einen weiteren <define name="meinBlock"> mit modifiziertem Inhalt, dann zieht dieser und überschreibt den inkludierten Inhalt. Nehmen wir an, obiger grammar-Block ist im File "myGrammer.rng" und wir haben
<grammar>
<include href="myGrammer.rng">
<define name="meinBlock">
<element name="Name">
<text/>
</element>
<element name="theEmail">
<text/>
</element>
</define> <!--define endet hier //-->
</include>
</grammar>
dann wird "Email" durch "theEmail" redefiniert!
<parentRef name=""> referenziert auf einen Define-Block außerhalb des aktuellen Grammatikblocks während <ref name=""> sich auf ein <define/> innerhalb des aktuellen Grammatikblocks bezieht.
combine=: Hat man mehrere gleichnamige Blöcke mit <define name="myBlock">, dann muss man mit dem Attribut combine="choice" oder combine="interleave" die "Vorfahrtsregel" festlegen.
<list>: Hat ein Textknoten mehrere durch white-spaces getrennte Werte, dann wird das durch "<list>" ausgedrückt. Beispiel: "Siehe-auch" kann ein oder mehrere Seiten-Verweise haben.
<
attribute name="Siehe-auch">
<
list>
<
zeroOrMore>
<
data type="token"/>
</
zeroOrMore>
</
list>
</
attribute>
<execpt>: Beschreibung von Ausnahmen innerhalb von <anyName>, <nsName> und <data>
<
element>
<
anyName>
<
except>
<
nsName ns=""/>
<
nsName ns="http://abc"/>
<
nsName ns="http://xyz"/>
</
except>
</
anyName>
<
ref name="anything"/>
</
element>
oder
<
data type="token">
<
except>
<
value>123</value>
</
except>
</
data>
<group>: Beschreibung einer geordneten Gruppe von Elementen. Wird gerne im Zusammenspiel mit <choice> verwendet.
<
element name="name">
<
choice>
<
text/>
<
group>
<
element name="first">
<
text/>
</
element>
<
optional>
<
element name="middle">
<
text/>
</
element>
</
optional>
<
element name="last">
<
text/>
</
element>
</
group>
</
choice>
</
element>
<element> und <define> beinhalten implizit dieses Tag.
Mehr Infos zu RelayNG unter http://books.xmlschemata.org/relaxng/page2.html