XML名前空間

概要

CDuceはW3CのXML名前空間の勧告を完全に実装している。アトム名(すなわちXML要素タグ)及びレコードのラベル(すなわちXML属性名)は、論理的には、名前空間URIとローカル部で構成されている。構文的には、修飾された名前でかかれ、勧告のQName生成と一致している。

QName     ::= (Prefix ':')? LocalPart
Prefix    ::= NCName
LocalPart ::= NCName

QNameの接頭辞は、名前空間URIに束縛されていなければならない。XMLにおいては、接頭辞から名前空間URIの束縛は、特別なxmlns:接頭辞の属性を用いて導入される。CDuceでは、その代わりに、明示的な名前空間束縛がある。例えば、XML文書、

<p:a q:c="3" xmlns:p="http://a.com" xmlns:q="http://b.com"/>
は、CDuceで次のように書くことができる。
namespace p = "http://a.com" in
namespace q = "http://b.com" in
<p:a q:c="3">[]

この要素は、次のようにlet束縛を用いて変数xに束縛することができる。

let x = 
  namespace p = "http://a.com" in
  namespace q = "http://b.com" in
  <p:a q:c="3">[]

この場合では、名前空間宣言はletのスコープローカルである。代わりに、グローバル接頭辞束縛を用いることができる。

namespace p = "http://a.com"
namespace q = "http://b.com"
let x = <p:a q:c="3">[]

同様に、CDuceは名前空間のデフォルト化をサポートしている。これはローカル及びグローバルのnamespace "..."コンストラクションで導入される。XMLにおけるのと同様に、デフォルトの名前空間はタグ(アトム)にだけ適用され、属性(レコードのラベル)には適用されない。例えば、式namespace "A" in <x y="3">[]においては、要素のタグに対する名前空間は"A"であるが、属性は名前空間を持たない。

トップレベル命令#envにより、CDuceは、現在のグローバル束縛の集合を、その他のものとともに、印字する。

名前空間宣言の再利用

グローバル名前空間宣言は、実は、現在のコンパイルユニットでエクスポートされる識別子を定義している。この識別子を他のユニットで用いて、同じ名前空間URIの接頭辞を再定義することができる。例えば、ユニットaが次を含んでいれば、

namespace ns = "http://a.com"

別のユニットでは、次のように宣言することができる。

namespace ans = a.ns

open文は名前空間宣言に対して作用する。openされたユニットの全ての宣言は現在のユニットで際エクスポートされる。

(現在のコンパイルユニット又は別のユニットで)XMLスキーマがある識別子に束縛されると、この識別子を名前空間接頭辞の右側で使うことができる。例:

schema s = "..."
namespace ns = s

アトムに対する型

Atomは、全ての名前空間における、全てのアトムを表現する。( <_>[]のような)タグ位置におけるアンダースコアもこの型を表す。

それぞれのアトムは、Atomの部分型を構成する。これらの単一型に加え、``名前空間の中であれば何でも''部分型があり、pを名前空間接頭辞として、p:*と書く。この型は、pが意味する名前空間の中の全てのアトムを持つ。トークン.:*は、現在のデフォルトの名前空間の中の全てのアトムを表現する。

XML文書の印字

print_xml及びprint_xml_utf8演算子は、XML文書の文字列表現を生成する。これの演算子は、接頭辞を名前空間に割り当てなければならない。現在の実装では、Cduceは、XML文書を、デフォルト名前空間なし、トップレベルの接頭辞束縛のみで生成する(つまり、xmlns:p="..."属性がルート要素に対してしか生成されない)。接頭辞名は、いくつかの演算子のスコープで束縛されている接頭辞を用いようとする。ヒューリスティックを用いて選ばれる。最初に、print_xmlこれができなければ、グローバル``ヒント''を用いる。(CDuceプログラムやロードしたXML文書で)接頭辞束縛に出会った時に毎回、名前空間に対するグローバルヒントを生成する。最後に、nを整数としてnsnの形式の新しい接頭辞を生成する。

print_xml (namespace "A" in <a>[])

接頭辞URI "A"に対する利用可能な名前がなければ、CDuceは新しい接頭辞を生成し、次のXML文書を生成する。

<ns1:a xmlns:ns1="A"/>

さて、次の式を考えてみる。

print_xml (namespace p = "A" in <p:a>[])

CDuceは次を生成する。

<p:a xmlns:p="A"/>

この場合、名前空間"A"に対する接頭辞束縛は、print_xmlのスコープにないが、名前pがグローバルヒントとして利用可能である。最後に、次を考えてみる。

namespace q = "A" in print_xml (namespace p = "A" in <p:a>[])

ここで、接頭辞qは、print_xmlのスコープで利用できる。したがって優先して用いられる。

<q:a xmlns:q="A"/>

最後の例として、次の式を考えてみる。

print_xml (namespace p ="A" in <p:a>[ (namespace p = "B" in <p:a>[]) ])

一つの名前pが、両方の名前空間"A"及び"B"に対して利用可能である。CDuceは、これを"A"に割り当てることを選び、"B"に対する新しい名前を生成するため、次を生成する。

<p:a xmlns:ns1="B" xmlns:p="A"><ns1:a/></p:a>

新しい名前はprint_xmlの適用に対して``ローカル''であることに注意すること。print_xmlを複数回適用すると、同じ名前ns1ns2、…を再利用することになる。

XMLの値及び型の清書

CDuceのインタプリタ及びトップレベルは、前の項で述べたのと似たアルゴリズムを用いて、名前空間を呼び出すCDuceの値及び型を清書する。

主要な相違は、現在の接頭辞束縛の集合をデフォルトで使わないことである。その論拠は、この集合が変化しうるので、CDuceの出力を理解するのが難しくなるからである。接頭辞が一度確保されると、別の名前空間に再利用されることはない。トップレベル命令#envを使うと、CDuceは清書に使われる接頭辞の表を、その他とともに、印字する。命令#reinit_nsを用いてこの表を再初期化することができる。この命令は、将来清書するための接頭辞を割り当てるヒントの一次ソースとして接頭辞束縛を使うかどうかを設定することもできる。

名前空間束縛へのアクセス

CDuceは、名前空間接頭辞が単に(CDuce又はXMLの)パーサもうpって解決されるマクロとして扱われる処理モデルを推奨している。しかしながら、XML仕様書の中には、各要素に対して、接頭辞から名前空間へのローカル束縛の集合を、見えるままにしておくように、アプリケーションに要求するものがある。CDuceはそれに対するサポートを提供する。

型システムに反映されていなくても、CDuceでは、XML要素に名前束縛の表をオプションで付け加えることができる。次のビルトイン関数により、プログラマはこの情報に明示的にアクセスすることができる。

type Namespaces = [ (String,String)* ]
namespaces: AnyXml -> Namespaces
set_namespaces: Namespaces -> AnyXml -> AnyXml

namespaces関数は、引数に名前空間情報が関連付けられていなければ、例外を発生させる。

XML要素が生成されると、CDuceコードの中のリテラルで、又load_xmlでCDuceにスコープ中の名前空間束縛を覚えるように指示することができる。これは、次のコンストラクションで行うことができる。

namespace on in e

eの中で作られたXML要素は、(load_xmlを呼び出すことによるものも含め)注釈を付けられる。同様に、部分式においてこの仕組みを切るnamespace offコンストラクションがある。又、両方のコンストラクションとも、トップレベルで使うことができる。

# namespace cduce = "CDUCE";;
# namespaces <cduce:a>[];;
Uncaught CDuce exception: [ `Invalid_argument 'namespaces' ]

# namespace on;;
# namespaces <cduce:a>[];;
- : Namespaces = [ [ "xsd" 'http://www.w3.org/2001/XMLSchema' ]
                   [ "xsi" 'http://www.w3.org/2001/XMLSchema-instance' ]
                   [ "cduce" 'CDUCE' ]
                   ]
# namespaces (load_xml "string:<a xmlns='xxx'/>");;
- : Namespaces = [ [ "" 'xxx' ] ]

接頭辞xmlへのデフォルトの束縛は、名前空間の結果には決して現れない。

xtransformイテレータは、単に横切ったXML要素に対して付加された名前空間の情報を変更することはしない。汎用の比較演算子では、関連付けられた名前空間の情報によるだけの違いしかない二つのXML要素を区別することはできない。

その他

XML 1.1におけるW3C名前空間勧告候補とは逆で、CDuceの宣言namespace p = ""は接頭辞pの宣言を取り消すことはしない。代わりに、空の名前空間に束縛する(つまり、この接頭辞を用いたQNameは名前空間を持っていないとして解釈される)