RELAX-NG スキーマの基本骨骼

原則

RELAX-NG では、要素/属性を定義する要素と、パターンを定義する要素(あるいは記述)があります。

要素/属性の定義について

XML 文書の基本骨骼を定義する要素です。 element, attribute 各要素をはじめ、中身を定義する text, empty, data, value などの各要素が、これに相当します。

パターンについて

文書の骨骼には直截関係せず、要素/属性/テキストの出現順位や頻度などを制馭するための要素です。choice, interleave, oneOrMore, group などの要素が、これに相当します。

基本的に、親要素の記述と子要素の記述が主従関係を結びます。例えば、選択肢を提供する choice 要素と複数記述を指示する oneOrMore 要素を使う場合、親子の関係によって解釈が以下のように変化します。

oneOrMore 要素が親、choice 要素が子
選択肢から選ぶ行為が、1回以上行える。
choice 要素が親、oneOrMore 要素が子
1回以上記述する行為が、選択肢の一つとなる。

スキーマの構成

ここでは、単一ファイルから成る(スタンドアローンな)スキーマに関して述べます。

ルート要素

名前空間

element 要素(要素を定義する要素)をルート要素とする場合

記述例
<?xml version="1.0" encoding="utf-8"?>
<element xmlns="http://relaxng.org/ns/structure/1.0"
   ns="http://garden.co.jp/" name="庭園"> <!-- ルートは"庭園"要素 -->
 <attribute name="名前"> <!-- "庭園"要素の"名前"属性を定義。-->
  <text/> <!-- 中身は任意のテキスト -->
 </attribute>
 <oneOrMore> <!-- "庭園"要素の中身は"植物"要素、1回以上。 -->
  <element name="植物">
   <text/>
  </element>
 </oneOrMore>
</element>
実際の XML 文書の一例
<?xml version="1.0" encoding="utf-8"?>
<庭園 名前="清流苑" xmlns="http://garden.co.jp/">
 <植物>ひのき</植物>
 <植物>薔薇</植物>
 <植物>かきつばた</植物>
</庭園>

grammar 要素をルート要素とする場合

記述例(働きは前述と全く同一)
<?xml version="1.0" encoding="utf-8"?>
<grammar xmlns="http://relaxng.org/ns/structure/1.0"
   ns="http://garden.co.jp/">

<start>
 <element name="庭園"> <!-- ルートは"庭園"要素 -->
  <ref name="garden-content"/> <!-- マクロ"garden-content"の埋め込み -->
 </element>
</start>

<define name="garden-content"> <!-- マクロ"garden-content"の定義 -->
 <attribute name="名前">
  <text/>
 </attribute>
 <oneOrMore>
  <element name="植物">
   <text/>
  </element>
 </oneOrMore>
</define>

</grammar>

要素の定義

要素は element 要素として定義します。 name 属性で要素名を、 element 要素の中身によってその属性の中身を、それぞれ定義出来ます。例えば、タイトル要素を定義したい場合は、以下のように記述します。

<element name="タイトル">
 …(タイトル要素の中身の定義)
</element>

詳しくは element 要素の項を御覧ください。

属性の定義

<element name="果物">
 <attribute name="味">
  <text/>
 </attribute>
 <text/>
</element>

実際には、以下のような XML 文書の断片が記述出来ることになります。

<果物 味="すっぱい">レモン</果物>

詳しくは、 attribute 要素の項を御覧ください。

中身の定義

テキストの定義

要素/属性いずれの場合においても、その中身を(何ら制限を持たない)テキストとしたい場合は、 text 要素によって明示します。

<element name="段落">
 <text/>
</element>

或は、ある選択肢のみを選ばせたい場合は、 value 要素と choice 要素を用います。例えば以下の例では、 背景色 要素の中身には、, , 黄色 のいずれかのテキスト値のみを記述することが出来ます。

<element name="背景色">
 <choice>
  <value>赤</value>
  <value>白</value>
  <value>黄色</value>
 </choice>
</element>

同じテキストでも、何らかの制限を持たせたい(字数制限をさせたい、あるいはある範囲内の数字のみを記述させたい)場合は、 text 要素の代わりに data 要素(及び param 要素)を用います。詳しくはデータ型の設定を御覧ください。

空要素の定義

要素の中身を空と定義したい場合は、 empty 要素を用います。例えば以下の場合、附加情報 要素は空要素となります。属性を併せて定義したい場合も同様です。

<element name="附加情報">
 <attribute name="項目"><text/></attribute>
 <attribute name="内容"><text/></attribute>
 <empty/>
</element>

実際の文書では、以下のような記述が許されることになります。当然、附加情報 要素の中身に子要素やテキストを入れることは許されません。

<附加情報 項目="製作者" 内容="波多野啓子"/>

子要素の定義

一つだけの場合

子要素, 子孫要素を定義したい場合は、 element 要素を入れ子にします。例えば 商品棚1 要素の中身に 商品 要素を一つ入れたい場合は、以下のように記述します。

<element name="商品棚1">
 <element name="商品">
  …
 </element>
</element>

ただし、その子要素の記述を必須としたくない場合には、 optional 要素を併用します。これで、商品要素は、0個もしくは1個記述出来ることになります。

<element name="商品棚1">
 <optional>
  <element name="商品">
   …
  </element>
 </optional>
</element>

同じものを複数入れたい場合

oneOrMore(一つ以上), zeroOrMore(0個を含む任意の個数) 各要素を使うことで、同じ要素を複数入れられるように出来ます。例えば、前述の例において、 商品 要素を一つ以上記述出来るようにするには、以下のように記述します。

<element name="商品棚1">
 <oneOrMore>
  <element name="商品">
   …
  </element>
 </oneOrMore>
</element>

詳しくは、 oneOrMore 及び zeroOrMore 要素の解説を御覧ください。

複数の要素(及びテキストや属性)から選択させたい場合

有限個の要素群から択一をさせる場合は、 choice 要素を用います。例えば以下の例では、 野菜, 果物, 乳製品 各要素のうちの一つが商品要素の中身となるよう、定義しています。

<element name="商品">
 <choice>
  <element name="野菜"> … </element>
  <element name="果物"> … </element>
  <element name="乳製品"> … </element>
 </choice>
</element>

選択肢の中身には、要素群のみならず、属性やテキストなども混在させることが可能です(これにより、例えば、とある要素の情報を子要素で書くか属性で書くかを選択できる)。詳しくは、 choice 要素の解説を御覧ください。

並列順序を重視したい場合

スキーマ例
<element name="料理">
 <attribute name="名前"><text/></attribute>
 <attribute name="分類"><text/></attribute>
 <element name="材料"><text/></element>
 <element name="下準備"><text/></element>
 <element name="調理"><text/></element>
 <element name="盛り附け"><text/></element>
</element>
XML 文書例
<料理 分類="サラダ" 名前="ヨーグルトサラダ">
 <材料>ヨーグルト、りんご、バナナ、蜜柑罐詰</材料>
 <下準備>りんごとバナナは細かく刻み、蜜柑は罐から出しておく。</下準備>
 <調理>果物を、ヨーグルトで和える。</調理>
 <盛り附け>透明ガラス容器に、小分けに盛り附ける。</盛り附け>
</料理>

上記の例では、出現する要素の順番が狂ってはいけません。例えば、材料要素と調理要素の順番を入れ換えたり、ということは出来ません。

順位不同だが、記述必須の中身が複数存在させたい場合

順位不同かつ必須事項が存在する場合、 interleave 要素を使うと便利です。例えば以下の例では、名刺要素の名前要素、肩書要素及び電話番号要素が、順位不同で必須となります。

スキーマ例
<element name="名刺">
 <interleave>
  <element name="名前"><text/></element>
  <element name="肩書"><text/></element>
  <element name="電話番号"><text/></element>
 </interleave>
</element>
実際の文書の例
<名刺>
 <肩書>理学博士</肩書>
 <電話番号>+81-222-12-3456</電話番号>
 <名前>田中玲菜</名前>
</名刺>

どれかを任意(オプション)要素としたい場合は、optional 要素を併用します。例えば電話番号のみをオプションとしたい場合は、以下のように記述します。

<element name="名刺">
 <interleave>
  <element name="名前"><text/></element>
  <element name="肩書"><text/></element>
  <optional>
   <element name="電話番号"><text/></element>
  </optional>
 </interleave>
</element>

詳しくは、 interleave 要素の項を御覧ください。