XML名前空間でタグを使い分ける技術者のためのXML再入門(6)

XML文書をさまざまなアプリケーションに処理させたいときなど、1つのXML文書に複数のボキャブラリを混在させたいことがある。そのためには、当初のXML文法に含まれていなかった「名前空間」という新しい考え方を導入する必要がある。本連載第6回は、XMLを飛躍的に使いやすくする「名前空間」の基本を解説する。

» 2002年04月17日 00時00分 公開
[吉田稔日本ユニテック]

名前空間とは

 XML 1.0の仕様では、1つのXMLデータを単一のDTDが支配する、つまり1つのXMLデータ(注1)は単一のボキャブラリ(注2)だけから構成されるという考え方をしていた。しかし、1つのXMLデータの中で、既存のボキャブラリを組み合わせて使えるようになれば、便利なだけでなく、開発コスト削減や開発期間短縮の点でも大変好ましいことだ。例えば、XHTMLの中で、数式を扱うMathMLが使えれば便利だろう。

(注1) W3CによるXMLの仕様書では、XMLで記述された情報を「XML文書(XML Document)」と呼んでいる。しかしXMLは、電子書籍などの文書以外に、電子商取引などのさまざまなデータの記述に用いられる。そこで、本連載ではXMLで記述された文書やデータを総称して「XMLデータ」と呼ぶことにする。

(注2) ボキャブラリとは、DTDなどによって定義された要素名を、まとめて呼ぶ一般的な名前。例えば、XHTMLで利用できる要素名をまとめて、「XHTMLのボキャブラリ」などと呼ぶ。


図1 名前空間を使うと、DTDによって定義された複数のボキャブラリが1つのXMLデータ内で扱えるようになる 図1 名前空間を使うと、DTDによって定義された複数のボキャブラリが1つのXMLデータ内で扱えるようになる

 しかし、1つのXMLデータの中で複数のボキャブラリを使用するとなると、要素名や属性名が重複する可能性がある。例えば、あるボキャブラリの中で「本のタイトル」を表すためにtitle要素が使われ、別のボキャブラリでは「人の肩書き」を表すためにtitle要素が使われる場合、この2つのボキャブラリを1つのXMLデータの中に混在させると、title要素が出てきたときに一体どちらの意味で使われているのか分からず、混乱が生じてしまう。

 こうした名前の衝突を避けるため、同じボキャブラリに属する要素や属性の名前を1つの集合としてとらえ、要素・属性の名前が同じであっても、属する集合が異なれば別の要素・属性と見なす、という考え方が導入された。この要素や属性の名前の集合を、名前空間(Namespace)と呼ぶ。また、ある要素・属性がどの名前空間に属しているのかを見分けるため、XMLの特別な書き方が考案された。この書き方を定めた規格を、XML名前空間(Namespaces in XML)と呼ぶ。

名前空間の書き方

 では、同じXMLデータに複数のボキャブラリを混在させても、要素・属性の名前が衝突しないようにするには、どんな書き方をしたらよいのだろうか。確実な方法は、1つ1つの名前空間に決して重複しない識別子を付けてやり、XMLデータ中でタグを記述するときにはその識別子と要素名をセットにして記述すればよい。

 XML名前空間では、決して重複しない識別子としてURIを使うことにしている。そして、適当な文字列を、名前空間URIを表す接頭辞(名前空間接頭辞:Namespace prefix)として宣言し、その名前空間接頭辞を、コロン“:”を挟んでタグ名と連結させることにより、ある要素がどの名前空間に属しているのかを明示できるようにしている。

 以下の例を使って説明しよう。これは、覚え書き(note)のためのボキャブラリで記述されたXMLデータ中に、セミナーのクラス(class)のためのボキャブラリで記述されたデータを混在させた例だ。2つのボキャブラリ間で“title”という要素名が重複しているが、名前空間によってこれれらの名前の衝突を回避できている。

<?xml version="1.0" ?>
<nt:note xmlns:nt ="http://www.utj.co.jp/dtd/note">
  <nt:title>セミナー予約</nt:title>
  <nt:p>今日、以下のセミナー申し込みがありました。</nt:p>
  <c:seminar xmlns:c="http://www.utj.co.jp/dtd/class">
    <c:course>XMLセミナー</c:course>
    <c:company>日本ユニテック(株)</c:company>
    <c:title>Web販売促進課課長</c:title>
    <c:name>遠山三郎</c:name>
  </c:seminar>
</nt:note>
リスト1 名前空間の使用例

 リスト1のルート要素の開始タグに下線を引いた。このタグの、「xmlns:nt ="http://www.utj.co.jp/dtd/note"」という属性の形をしているところが、名前空間を宣言しているところだ。ここでは、名前空間URI“http://www.utj.co.jp/dtd/note”に、“nt”という文字列を名前空間接頭辞として結び付ける、ということが宣言されている。この結果、“nt”という接頭辞で修飾される要素(リスト1におけるnt:note要素やnt:tittle要素、nt:p要素)は、この名前空間に属していることを明示できるようになる。

名前空間の有効範囲

 ある要素の開始タグで名前空間を宣言すると、その要素、およびその要素の下位要素において、その名前空間が有効になる。従って、ルート要素で宣言された名前空間は、XMLデータ全体で有効になり、XMLデータ全体のどこでもその名前空間を使用できる。リスト1において、“nt”という名前空間接頭辞が付けられた名前空間は、ルート要素で宣言されている。その有効範囲は、リスト1’において濃い青色で示した範囲となる。

<?xml version="1.0" ?>
<nt:note xmlns:nt ="http://www.utj.co.jp/dtd/note">
  <nt:title>セミナー予約</nt:title>
  <nt:p>今日、以下のセミナー申し込みがありました。</nt:p>
  <c:seminar xmlns:c="http://www.utj.co.jp/dtd/class">
    <c:course>XMLセミナー</c:course>
    <c:company>日本ユニテック(株)</c:company>
    <c:title>Web販売促進課課長</c:title>
    <c:name>遠山三郎</c:name>
  </c:seminar>
</nt:note>
リスト1’ ルート要素で名前空間を宣言した場合の有効範囲

 一方、ある名前空間を特定の要素およびその下位要素だけで使用する場合のように、名前空間を局所的に宣言したいこともある。その場合、名前空間を使用したい要素、またはそれより上位の要素で宣言すればよい。

 リスト1において局所的な名前空間の宣言をしているところを以下のリスト1”に下線を引いた行で示す。ここでは、名前空間宣言がc:seminar要素の開始タグで行われている。従って、“c”という名前空間接頭辞で識別される名前空間の有効範囲は、リスト1”において緑色で示した範囲となる。

<?xml version="1.0" ?>
<nt:note xmlns:nt ="http://www.utj.co.jp/dtd/note">
  <nt:title>セミナー予約</nt:title>
  <nt:p>今日、以下のセミナー申し込みがありました。</nt:p>
  <c:seminar xmlns:c="http://www.utj.co.jp/dtd/class">
    <c:course>XMLセミナー</c:course>
    <c:company>日本ユニテック(株)</c:company>
    <c:title>Web販売促進課課長</c:title>
    <c:name>遠山三郎</c:name>
  </c:seminar>

</nt:note>
リスト1’’ 局所的に名前空間を宣言した場合の有効範囲

 しかし、局所的に宣言された名前空間が何度も出てくる場合、同じ宣言をその都度書いていくのは効率的ではない。リスト2のように、ルート要素の開始タグで一括して宣言しておくのがよいだろう。

<?xml version="1.0" ?>
<nt:note xmlns:nt = http://www.utj.co.jp/dtd/note
xmlns:c=http://www.utj.co.jp/dtd/class>

  <nt:title>セミナー予約</nt:title>
  <nt:p>今日、以下のセミナー申し込みがありました。</nt:p>
  <c:seminar>
    <c:seminame>XMLセミナー</c:seminame>
    <c:company>日本ユニテック(株)</c:company>
    <c:title>Web販売促進課課長</c:title>
    <c:name>遠山三郎</c:name>
  </c:seminar>
</nt:note>
リスト2 ルート要素で一括して宣言した例

デフォルトの名前空間

 すべての要素について名前空間接頭辞を書くのは煩雑だ。そのため、名前空間のデフォルト値を宣言する仕組みが用意されている。デフォルトの名前空間を宣言した例を下記のリスト3に示す。

<?xml version="1.0" ?>
<nt:note xmlns="http://www.utj.co.jp/dtd/note">
  <title>セミナー予約</title>
  <p>今日、以下のセミナー申し込みがありました。</p>
  <c:seminar xmlns:c="http://www.utj.co.jp/dtd/class">
    <c:course>XMLセミナー</c:course>
    <c:company>日本ユニテック(株)</c:company>
    <c:title>Web販売促進課課長</c:title>
    <c:name>遠山三郎</c:name>
  </c:seminar>
</note>
リスト3 デフォルトの名前空間の使用例

 リスト3において、下線を引いたところが、デフォルトの名前空間を宣言しているところだ。xmlnsの後に、すぐ“=”がきているところがいままでと異なっている。

 デフォルトの名前区間宣言は、名前空間接頭辞を省略して宣言すればよい。こうすれば、デフォルトの名前空間宣言をした要素および下位要素において、名前空間接頭辞の付いていない要素は、名前空間URI“http://www.utj.co.jp/dtd/note”に属するものと見なされる。

グローバル属性

 要素から少し離れて、属性についても触れておこう。

 XML 1.0のDTDにおいて、属性は特定の要素型に従属していた。しかし、属性の中には、複数の要素の間で共通して指定される属性がある。例えばファイル名を指定する“src”属性や、データ型を指定する“type”属性などだ。これらは従来、こうした属性を使いたい要素に対する属性リスト宣言でいちいち指定しなければならず、非常に冗長な作業だった。

 名前空間では、こうした「どこでも使える」属性をさらに拡張してグローバル属性という名前で定義している。あるボキャブラリで定義されている属性は、その名前空間接頭辞を付けることでどの要素での使用も許している(別の名前空間に属する要素でも構わない)。

 “src”という名前を持つ属性を、グローバル属性として使用した例を以下に示す。属性が名前空間接頭辞(例では“gen”)で修飾されていることに注意していただきたい。

<p>下図に昨年度営業実績表を示す。</p>
<fig gen:src="http://www.utj.co.jp/sales/tsales2001"/>
リスト4 グローバル属性の例

名前空間URIにDTDがあるとは限らない

 名前空間がURIによって一意に決まることから、名前空間のURIとは、そのボキャブラリを定義しているDTDやほかのスキーマ定義ファイルが存在する場所を指していると思う方もおられるかもしれない。実は、これはよくある誤解だ。名前空間URIは、あくまで名前空間を世界中で一意に決めるための文字列にすぎない。従って、このURIに何らかのスキーマ定義ファイルがあるとは限らない(あってもなくてもよい)。

 これを例証してみよう。XSLTとは、W3Cが規格化したXMLの構造変換を記述する言語だが、XSLTのボキャブラリを使用するには、以下のURIの名前空間を宣言する必要がある。では、このXSLTの名前空間を指定しているURI(正確にはURL)に何があるか参照してみてほしい。

http://www.w3.org/1999/XSL/Transform

 XSLTのボキャブラリのためのDTDがあると思いがちだが、そのようなものはないことをご理解いただけるだろう。

名前空間の利用例

 では、どんなときに名前空間を使用したらよいのだろうか? 例えば、社内の各部署で共通して使えるボキャブラリや、他社とやりとりするために業界標準ボキャブラリがあったとして、その一部を自分が作成するXML文書の一部に利用する場合などは、名前空間を使用することでそれらを便利に使えるだろう。要素名や属性名の衝突を心配せずに、標準のボキャブラリを流用できる。

 リスト5の例は、収支報告書の中で社内共通の売り上げDTDを流用しているケースだ。

<?xml version="1.0" encoding="shift_jis"?>
<accountS xmlns ="http://www.utj.co.jp/dtd/accounts"
xmlns:sl ="http://www.utj.co.jp/dtd/sales" >
  <title>第一四半期収支報告書</title>
  <summary>今期の当社を取り巻く環境の変化はめまぐるしく…</summary>
  ……
  <sl:division>
    <sl:name>システム・ソリューション</sl:name>
    <sl:sales>645,200,000</sl:sales>
    ……
  </sl:division>
  ……
</accountS>
リスト5 収支報告書の中で売り上げDTDを使う

 接頭辞“sl”が付けられている要素が、売り上げDTD(名前空間URIが“http://www.utj.co.jp/dtd/sales”)から流用しているところだ。一方、接頭辞が付いていない要素は、デフォルトの名前空間(名前空間URIが“http://www.utj.co.jp/dtd/accounts”) として宣言されている収支報告書の要素だ。

 複数のアプリケーションで処理されることを想定したXMLデータでは、名前空間を使用することによって、それぞれのアプリケーションが使用する要素・属性を明示できるようになる。その例をリスト6に示す。これは、本文テキスト部分と数式の部分と図形の部分からなるXMLデータで、それぞれの表示には異なるアプリケーションによる処理が必要なケースだ。そのため、ブラウザ表示のためのXHTMLによる記述中に、数式表示のためのMathMLとベクターグラフィック表示のためのSVGによる記述が含まれている。

<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN""http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <body>
    <h1>The Equation of a circle:</h1>
    <p>
      <m:math m:xmlns="http://www.w3.org/1998/Math/MathML">
        <m:mi>x</m:mi>
        <m:mn>2</m:mn>
        <m:mo>+</m:mo>
        <m:mi>y</m:mi>
        <m:mn>2</m:mn>
        <m:mo>=</m:mo>
        <m:mn>1</m:mn>
      </m:math>
    </p>
    <s:svg s:xmlns="http://www.w3.org/2000/svg">
      <s:circle stroke="black" fill="none" cy="82px" cx="82px" r="82px"/>
    </s:svg>
  </body>
</html>
リスト6 XHTMLファイル中でSVGとMathMLを使う。ページ全体のレイアウトは、XHTMLによる処理が必要であり、数式表示の処理には、MathMLに基づいたベクターグラフィック処理が必要となる

 ここで、XHTMLに属する要素・属性は、XMLデータ全体のデフォルトの名前空間として宣言されている。また、MathML とSVGの名前空間は、それぞれ“m”と“s”が名前空間接頭辞として宣言されている。これをW3CによるリファレンスブラウザAmaya 5.3で表示すると画面1のようになる。XHTMLとMathMLの処理が同居しているのが分かるだろう。

画面1 AmayaでXHTMLとMathMLを混在させて表示した例 画面1 AmayaでXHTMLとMathMLを混在させて表示した例

今回のまとめ

 今回は、XMLの利用の幅を広げることになるXML名前空間の基本的な事柄を解説した。XML名前空間は、実際に業務で使われているXMLデータでよく見掛けるので、理解を確実にしておきたいものだ。さらに詳しいことを知りたい方は、XML名前空間の仕様書や関連記事をご覧いただきたい。

 次回は、XMLデータのWebブラウザによる表示や、異なるスキーマ間でのデータ交換の場面で必要となる、XMLデータの構造変換技術「XSLT」の基本を解説する。



Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。