xmlns:xx
宣言中の URI にあります。 RERLAX-NG では、接頭辞と URI の対応が的確になされていれば、接頭辞自身の名前に依存せず検証を行うことが出来ます。宣言すべき名前空間が一つだけの場合、スキーマの記述は2通りあります。以下にその例を紹介します。
<grammar xmlns="http://relaxng.org/ns/structure/1.0" ns="http://cafe.co.jp/"> <start> <element name="喫茶"> <text/> </element> </start> </grammar>
<grammar xmlns="http://relaxng.org/ns/structure/1.0" xmlns:cafe="http://cafe.co.jp/"> <start> <element name="cafe:喫茶"> <text/> </element> </start> </grammar>
いずれの場合も働きは同一で、以下の文書はいずれも正当なものと見倣されます。
<?xml version="1.0" encoding="utf-8"?> <喫茶 xmlns="http://cafe.co.jp/"> ジャズCafe レナ </喫茶>
<?xml version="1.0" encoding="utf-8"?> <店:喫茶 xmlns:店="http://cafe.co.jp/"> ジャズCafe レナ </喫茶>
先程述べた通り、名前空間の本質は URI にあるので、接頭辞自体はスキーマと同一である必要はありません。
一つの言語(の名前空間)をデフォルトにする方法と、全ての要素宣言で有修飾名を使う方法と、二通りあります。以下の例では、二つの名前空間を有する文書を検証するためのスキーマを紹介します。
<grammar xmlns="http://relaxng.org/ns/structure/1.0" ns="http://cafe.co.jp/" xmlns:data="http://data.org/"> <start> <element name="喫茶"> <element name="data:住所"><text/></element> </element> </start> </grammar>
<grammar xmlns="http://relaxng.org/ns/structure/1.0" xmlns:cafe="http://cafe.co.jp/" xmlns:data="http://data.org/"> <start> <element name="cafe:喫茶"> <element name="data:住所"><text/></element> </element> </start> </grammar>
また、限られた要素内でのみ違う名前空間の要素を用いたい場合は、局所的に宣言することも可能です。以下に、上記の二例と同じ働きをするスキーマの一例を示します。
<grammar xmlns="http://relaxng.org/ns/structure/1.0" xmlns:cafe="http://cafe.co.jp/"> <start> <element name="cafe:喫茶"> <element name="data:住所" xmlns:data="http://data.org/"><text/></element> </element> </start> </grammar>
実際には、一つのファイルで複数の名前空間を用いることは少なく、大抵は異る名前空間を有する複数のファイル(モジュール)を組み合わせることが多いかと思われます。そのような場合、マクロを扱う define
, ref
各要素, 外部スキーマを取り込む include
要素を用いて、以下のような記述が可能となります。
<grammar xmlns="http://relaxng.org/ns/structure/1.0" ns="http://cafe.co.jp/"> <start> <element name="喫茶"> <ref name="cafe-content"/> <!-- 従スキーマ内のマクロを指定 --> </element> </start> <include href="sub.rng"/> <!-- 従スキーマの取り込み --> </grammar>
<grammar xmlns="http://relaxng.org/ns/structure/1.0" ns="http://data.org/"> <define name="cafe-content"> <!-- 従スキーマ内のマクロ --> <element name="住所"><text/></element> </define> </grammar>
<grammar xmlns="http://relaxng.org/ns/structure/1.0" ns="http://cafe.co.jp/"> <start> <element name="喫茶"> <ref name="cafe-content"/> <!-- 従スキーマ内のマクロを指定 --> </element> </start> <include href="sub.rng"/> <!-- 従スキーマの取り込み --> </grammar>
<grammar xmlns="http://relaxng.org/ns/structure/1.0" xmlns:data="http://data.org/"> <define name="cafe-content"> <!-- 従スキーマ内のマクロ --> <element name="data:住所"><text/></element> </define> </grammar>
<grammar xmlns="http://relaxng.org/ns/structure/1.0" xmlns:cafe="http://cafe.co.jp/"> <start> <element name="cafe:喫茶"> <ref name="cafe-content"/> <!-- 従スキーマ内のマクロを指定 --> </element> </start> <include href="sub.rng"/> <!-- 従スキーマの取り込み --> </grammar>
<grammar xmlns="http://relaxng.org/ns/structure/1.0" xmlns:data="http://data.org/"> <define name="cafe-content"> <!-- 従スキーマ内のマクロ --> <element name="data:住所"><text/></element> </define> </grammar>
属性が入らない場合は三例いずれの記述でも問題ありませんが、属性を併せて定義する場合は、いくつか注意すべき点があります。それを次の項で述べます。
属性の定義が入り込む場合、とりわけモジュールの作成には注意しなければならないことがあります。例えば、以下の二つのモジュールを取り込む場合を考えてみます。
<grammar xmlns="http://relaxng.org/ns/structure/1.0" ns="http://cafe.co.jp/"> <start> <element name="喫茶"> <ref name="cafe-attribute"/> <zeroOrMore> <ref name="cafe-content"/> </zeroOrMore> </element> </start> <define name="cafe-attribute" combine="interleave"> <attribute name="店名"><text/></attribute> </define> <define name="cafe-content" combine="choice"> <element name="メニュー"><text/></attribute> </define> <include href="sub.rng"/> </grammar>
<grammar xmlns="http://relaxng.org/ns/structure/1.0" ns="http://garden.co.jp/"> <define name="cafe-attribute" combine="interleave"> <attribute name="庭園"><text/></attribute> </define> <define name="cafe-content" combine="choice"> <element name="植物"><text/></element> </define> </grammar>
<?xml version="1.0"?> <喫茶 xmlns="http://cafe.co.jp/" xmlns:庭園="http://garden.co.jp/" 店名="モダン喫茶レナ" 庭園:庭園="ローズガーデン"> <メニュー>フルーツパフェ</メニュー> <庭園:植物>薔薇</庭園:植物> </喫茶>
庭園:庭園
属性は定義されていない
」と言われ、さらには「必須属性が欠落している」というエラーが出てしまいます(要素に関してはエラーは出ません)。
接頭辞が附属した属性は「グローバルな」属性です。いかなる名前空間の属するいかなる要素に記述されても、その属性は「属性特有の名前空間を有する属性」です。
要素の開始タグにて、接頭辞無しの属性が記された場合、その属性は「ローカルな」属性になります。具体的には、「とある名前空間に属する、その要素に属する属性」となります。同じ名前空間に属する要素であっても違う要素に附属する場合、その属性の所属は異ることになります。
例えば、以下の例を考えてみます。
<?xml version="1.0"> <喫茶 xmlns="http://cafe.co.jp/" xmlns:cafe="http://cafe.co.jp/"> <cafe:メニュー cafe:名前="フルーツパフェ"/> <cafe:メニュー 名前="コーヒー"/> </喫茶>
上の文にある二つの 名前
と cafe:名前
は同じように見えますが、所属が異ります。前者の cafe:名前
属性はグローバル属性で、「名前空間 http://cafe.co.jp/
に属する 名前
属性」ですが、後者はローカル属性で、「名前空間 http://cafe.co.jp/
に属する メニュー
要素に属する、 名前
属性」となります。
attribute
要素で宣言した場合、それらはすべてローカルな属性となります。個々のモジュールを作成する際には、名前空間の宣言には、それぞれのデフォルト名前空間を宣言する ns
属性をルート要素で使えば充分です。ns
属性は使えず、必ず xmlns:xx
属性を用いなければなりません。xml
接頭辞がある予約属性( lang
, base
など)は、常にグローバル属性として扱われます。名前空間を別途宣言する必要はありません。前述の例において、庭園:庭園
属性を異る名前空間に属する 喫茶
要素で用いる場合、従スキーマの sub.rng を以下のように修正する必要があります。
<grammar xmlns="http://relaxng.org/ns/structure/1.0" xmlns:庭園="http://garden.co.jp/"> <define name="cafe-attribute" combine="interleave"> <attribute name="庭園:庭園"><text/></attribute> </define> <define name="cafe-content" combine="choice"> <element name="庭園:植物"><text/></element> </define> </grammar>
これで 庭園:庭園
属性はグローバル属性となり、適切に文書を検証出来るようになります。