今回は外部参照をする要素。
- <externalRef>
- <include>
どちらも参照する外部ファイルを指定する属性「@href 属性」を持たなければなりません。
<externalRef> 要素
<externalRef> 要素は、外部ファイルに定義されているパターンをそのまま読み込む要素です。 パターンが書けるところには何処にでも書けます。 また、外部ファイルは RELAX NG パターンが定義されていればどんなものでも構いません。
簡単なサンプルを見てみましょう。 まず、以下のように <child> 要素を定義するスキーマがあったとします(ファイル名は「child.rng」とします):
<!-- child.rng --> <element name="child" xmlns="http://relaxng.org/ns/structure/1.0"> <empty/> </element>
他のスキーマ定義からこの要素の定義をそのまま読み込みたい場合、以下のように <externalRef> 要素を書きます:
<element name="parent" xmlns="http://relaxng.org/ns/structure/1.0"> <externalRef href="child.rng"/> </element>
この結果、以下のようなスキーマ定義と同じと見なされます:
<element name="parent" xmlns="http://relaxng.org/ns/structure/1.0"> <element name="child"> <empty/> </element> </element>
<externalRef> 要素の箇所が参照されているスキーマ定義で単純に置き換えられるだけです。
★@ns 属性★
<externalRef> 要素は単に参照先のスキーマ定義に置き換えられるだけですが、@ns 属性がある場合はそれが参照先のスキーマ定義に付加されます。 詳しくはそのうちに。
<include> 要素
<include> 要素は外部ファイルのパターン定義(<define> 要素)を読み込む要素です。 <grammar> 要素の子要素として用います。 また、<externalRef> 要素と違って、参照先のスキーマ定義は <grammar> 要素でなければいけません。
サンプルを見てみましょう。 参照先のファイル「child-def.rng」は以下のようであったとします:
<!-- child-def.rng --> <grammar xmlns="http://relaxng.org/ns/structure/1.0"> <define name="child1">...</define> <define name="child2">...</define> <define name="child3">...</define> </grammar>
このとき、<include> 要素を含むスキーマ定義以下のように書くと
<grammar xmlns="http://relaxng.org/ns/structure/1.0"> <include href="child-def.rng"/> <define name="parent1">...</define> <define name="parent2">...</define> <define name="parent3">...</define> </grammar>
以下のようなスキーマ定義と同じになります:
<grammar xmlns="http://relaxng.org/ns/structure/1.0"> <define name="child1">...</define> <define name="child2">...</define> <define name="child3">...</define> <define name="parent1">...</define> <define name="parent2">...</define> <define name="parent3">...</define> </grammar>
★同名の <define> 要素がある場合★
参照先にも参照元にも同名の <define> 要素がある場合、それらの複数の定義は @combine 属性を用いて適切に結合されます。 詳しくはそのうちに。 複数の同名の <define> 要素に @combine 属性がない場合はエラーになります。
★子要素としての <start>, <define> 要素★
<include> 要素には、子要素として <start>, <define> 要素を書くことができます*1。 これによって、参照先の <start> 要素や <define> 要素を上書きすることができます。
<include> 要素下に <define> 要素があるサンプルを見てみましょう。 参照元のスキーマ定義を以下のように書くと(「child-def.rng」の内容は上記のサンプルと同じとします)、
<grammar xmlns="http://relaxng.org/ns/structure/1.0"> <include href="child-def.rng"> <define name="child1">○○○</define> </include> ... </grammar>
以下のスキーマ定義と同じになります:
<grammar xmlns="http://relaxng.org/ns/structure/1.0"> <define name="child1">○○○</define> <define name="child2">...</define> <define name="child3">...</define> ... </grammar>
<include> 要素下に <start> 要素を書いた場合も、参照先の <grammar> 要素下の <start> 要素がそのまま上書きされます。
注意しなければならないのは、この「上書き」方法には「上書きされる相手」が無ければいけないことです。 <include> 要素下に <define> 要素を書いた場合、参照先のスキーマ定義に同名(@name 属性の値が同じ)の <define> 要素が定義されていなければいけません*2。