uhyohyo.net

JavaScript初級者から中級者になろう

六章第二回 名前空間

このページの最終更新日:

XMLの、HTMLにはない特徴として、名前空間というものがあります。今回、それについて解説します。

名前空間があるXMLの具体例を見てみます。


<?xml version="1.0" ?>
<aaa:abc xmlns:aaa="http://example.com/aaa">
  <aaa:abcd a="aaaaaaaa" />
  <aaa:abcd a="bbbbbbbb" />
  <aaa:abcd a="cccccccc" />
</aaa:abc>

この文書では、タグ名の全てに最初に「aaa:」がついています。この部分が名前空間を表すものです。

このとき、タグabcやabcdはaaaに属しているという意味になります。abc要素に謎の「xmlns:aaa」という属性がありますが、これについては後で説明します。

また、このように複数の名前空間を使うことも可能です。


<?xml version="1.0" ?>
<root xmlns:aaa="http://example.com/aaa" xmlns:bbb="http://example.com/bbb">
  <aaa:abcd a="aaaaaaaa" />
  <aaa:abcd a="bbbbbbbb" />
  <aaa:abcd a="cccccccc" />
  <bbb:abcd>aaaaaaaa</bbb:abcd>
  <bbb:abcd>bbbbbbbb</bbb:abcd>
  <bbb:abcd>cccccccc</bbb:abcd>
</root>

aaaに属しているのもbbbに属しているのもabcdタグですね。今回は、ルート要素であるrootタグはこれらの名前空間に属していません。

実は、同じabcdでも、aaaに属するそれとbbbに属するそれは異なる要素として扱われます。

逆に、


<?xml version="1.0" ?>
<root xmlns:aaa="http://example.com/aaa">
  <aaa:abc />
  <aaa:def />
  <aaa:ghi />
</root>

名前空間の実体

実はここまで、「aaaに属する」という言い方はしても「aaaが名前空間である」とは言っていません。実は、上の例では名前空間はxmlns:aaa属性で定義されています。上の例では、"http://example.com/aaa"が名前空間です。aaa自体は名前空間接頭辞といい、aaaという名前空間接頭辞が表す名前空間がhttp://example.com/aaaです。この関係がxmlns:aaa属性によって定義されています。正確に述べると、名前空間を定義するには次のような属性を書きます。

xmlns:名前空間接頭辞 ="URI"

これはどの要素にも書くことができます。これにより名前空間とそれに対応する名前空間接頭辞が定義されます。ここで定義された名前空間接頭辞は、その要素自身およびその中の要素で使うことができます。使うというのは、<aaa:abc />のようにタグ名の前につけて使うということです。

このURIこそが名前空間の本体といえます。例えば「aaa:abcd」というタグは、名前空間接頭辞のaaaが表す名前空間http://example.com/aaaに属する要素abcdということです。

ちなみに、名前空間がURLの場合など、そのURLが表すインターネット上のページなどが存在しなくても構いません。実際に存在するサイトのURLでなくてもよいということです。

それならなぜURIを使うかというと、重複する可能性が低いからです。一般的にWebサイトは誰かの所有物となるので、関係ない人が他人のWebサイトのURLを使うことは考えにくいですね。

名前空間の意味

上記の重複しにくいというのは、名前空間に意味を持たせるということに関連しています。

一般に、XMLを用いてデータフォーマットを作る場合、そこで使われる要素が属するための名前空間を定義するのがよいでしょう。例えば、あなたがユーザーリストの書き方を考えだして使ったとします。前回の


<?xml version="1.0" ?>
<users>
  <ユーザー>
    <名前>Aさん</名前>
    <年齢>23</年齢>
  </ユーザー>
  <ユーザー>
    <名前>Bさん</名前>
    <年齢>100</年齢>
  </ユーザー>
</users>

を使ってみましょう。

ここで、これに出てきている要素名(users、ユーザー、名前、年齢)やその使い方(usersの子はユーザーで、ユーザーの子は名前と年齢…)はこの「ユーザーリスト」のための要素です。

ここで、このユーザーリストをひとつの名前空間に属するようにすると、こうなります。


<?xml version="1.0" ?>
<users:users xmlns:users="http://example.com/users">
  <users:ユーザー>
    <users:名前>Aさん</users:名前>
    <users:年齢>23</users:年齢>
  </users:ユーザー>
  <users:ユーザー>
    <users:名前>Bさん</users:名前>
    <users:年齢>100</users:年齢>
  </users:ユーザー>
</users:users>

ここで、この名前空間「http://example.com/users」とこれらの要素が結びついたことになります。つまり、ここで「users」とか「ユーザー」とかいっている要素は、実は名前空間「http://example.com/users」に属する要素を使っているということになります。

このように結びつけることが何の役に立つのかというと、例えば他のXML文書(やXHTML文書)でこのデータフォーマットを使いたいときに役に立ちます。

例えば、次のようなXML文書を考えます。


<?xml version="1.0" ?>
<aaa>
  <bbb>あああ</bbb>
  <bbb>あああ</bbb>
  <ccc>
    <users>
      <ユーザー>
        <名前>Cさん</名前>
        <年齢>-5</年齢>
      </ユーザー>
    </users>
  </ccc>
</aaa>

ccc要素の下で、さっきの「ユーザーリスト」の要素が使われているのがわかります。

ところが、この文書全体は何らかの別のフォーマットに従っているはずです。しかし「ユーザーリスト」の部分はそれとは独立した別のフォーマットを利用しているので、これらは区別したくなります。ここで出てくるのが名前空間です。

ユーザーリストの部分を文書とは別の名前空間に属するようにすれば、その部分が独立したフォーマットに従っていることを明示できます。すなわち、


<?xml version="1.0" ?>
<aaa>
  <bbb>あああ</bbb>
  <bbb>あああ</bbb>
  <ccc>
    <users:users xmlns:users="http://example.com/users">
      <users:ユーザー>
        <users:名前>Cさん</users:名前>
        <users:年齢>-5</users:年齢>
      </users:ユーザー>
    </users:users>
  </ccc>
</aaa>

こうすることで、users以下の「ユーザーリスト」の語彙は、名前空間「http://example.com/users」に属するようになりました。

自分でデータフォーマットを作った場合、このように名前空間を定めておくことで、どのXML文書で使われてもどのデータフォーマットに由来するのかわかるようになります。

とはいえ、実際に自分で名前空間を作ることは少ないでしょう。実際には、XHTMLやSVGなど既存のフォーマットにはちゃんと名前空間が定義されていますから、それをちゃんと扱えるようになることが名前空間を学ぶ大きな意義です。

デフォルト名前空間

実は、デフォルト名前空間というものがあります。それはつまり、名前空間接頭辞の無いタグがどの名前空間に属するかということです。

実は、それはあらかじめ決めることができます。


<?xml version="1.0" ?>
<aaa xmlns="http://example.com/">
  <bbb>あああ</bbb>
  <bbb>あああ</bbb>
</aaa>

このサンプルで、aaa要素はxmlnsという属性を持っています。xmlns:名前空間接頭辞という形の、接頭辞の部分が省略された形だといえますね。

この形で、接頭辞のないタグが属する名前空間を指定することができます。これがデフォルト名前空間です。ちなみに、


<?xml version="1.0" ?>
<aaa>
  <bbb>あああ</bbb>
  <bbb>あああ</bbb>
</aaa>

のようにxmlnsも無い場合は、「名前空間が無い」という扱いになります。

デフォルト名前空間を用いることで、名前空間接頭辞を何回も書くのを避けることができます。例えば上の


<?xml version="1.0" ?>
<aaa>
  <bbb>あああ</bbb>
  <bbb>あああ</bbb>
  <ccc>
    <users:users xmlns:users="http://example.com/users">
      <users:ユーザー>
        <users:名前>Cさん</users:名前>
        <users:年齢>-5</users:年齢>
      </users:ユーザー>
    </users:users>
  </ccc>
</aaa>

というXML文書は、users要素以下全てのタグにusersという接頭辞をつけなければならず見にくいので、このようにできます。


<?xml version="1.0" ?>
<aaa>
  <bbb>あああ</bbb>
  <bbb>あああ</bbb>
  <ccc>
    <users xmlns="http://example.com/users">
      <ユーザー>
        <名前>Cさん</名前>
        <年齢>-5</年齢>
      </ユーザー>
    </users>
  </ccc>
</aaa>

users接頭辞がなくなりました。上記のように、接頭辞がない場合はデフォルト名前空間に属しますが、xmlnsでデフォルト名前空間をhttp://example.com/usersにしたから、結局users要素以下は変更前と同じhttp://example.com/usersに属することになります。

上のほうで解説したとおり、xmlnsの適用範囲はその要素以下なので、usersの外側には影響はありません。このように、全部のタグに名前空間接頭辞をつけるのは見づらいし億劫なので、このようにデフォルト名前空間を設定して省略することがよく行われます。

XHTMLと名前空間

ここで、XHTMLの話題に戻ります。前述のように、XHTMLは決まった名前空間に属することになっています。その名前空間は、http://www.w3.org/1999/xhtmlです。

だから、XHTMLは、例えば名前空間接頭辞をxhtmlとしたとき、


<?xml version="1.0" ?>
<xhtml:html xmlns:xhtml="http://www.w3.org/1999/xhtml">
  <xhtml:head>
    <xhtml:meta charset="UTF-8" />
    <xhtml:title>タイトル</xhtml:title>
  </xhtml:head>
  <xhtml:body>
    <xhtml:p>サンプル</xhtml:p>
  </xhtml:body>
</xhtml:html>

という感じにします。ただ、一目見て分かるようにとても見にくいです。そこで、大抵の場合、デフォルト名前空間を用いて次のようにします。

<?xml version="1.0" ?>
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta charset="UTF-8" />
    <title>タイトル</title>
  </head>
  <body>
    <p>サンプル</p>
  </body>
</html>

これならとてもすっきりして、HTMLとそこまで変わらなくなりました。

多くのXHTML文書には呪文のようにこのxmlns属性が書いてあります。それは、デフォルト名前空間を定めることで各要素がちゃんとXHTMLの名前空間に属するようにするためだったのです。

ちなみに、XHTML文書では、XHTMLの名前空間に属する要素だけが意味のあるHTML要素として解釈されます。例えば、次の例を試してみましょう。

<?xml version="1.0" ?>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:myns="http://example.com/">
  <head>
    <meta charset="UTF-8" />
    <title>タイトル</title>
  </head>
  <body>
    <p>サンプル</p>
    <p>これは<strong xmlns="http://example.com/">重要</strong>です。</p>
  </body>
</html>

なお、この例ではファイルの拡張子を.xhtmlとする必要があります。そうしないと、XHTMLではなくただのHTMLとして解釈されてしまいます。

さて、拡張子.xhtmlでこの例を保存してブラウザで開くと、strong要素は一般に太字で描画されるにも関わらず、この例では太字にならないはずです。

この理由は、strong要素にxmlns属性があるためデフォルト名前空間が変わり、結果としてstrong要素はXHTMLの名前空間に属していないからです。その結果、このstrong要素はHTMLのstrong要素であるとは解釈されず、太字にならないのです。

また、実は、XHTMLはXMLなので、他の名前空間に属していればXHTML以外の要素を使用してもよいです。

だから、次のようなことが可能です。


<?xml version="1.0" ?>
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta charset="UTF-8" />
    <title>ユーザー一覧</title>
  </head>
  <body>
    <p>ユーザーの一覧です。</p>
    <users xmlns="http://example.com/users">
      <ユーザー>
        <名前>Dさん</名前>
        <年齢>35</年齢>
      </ユーザー>
      <ユーザー>
        <名前>Eさん</名前>
        <年齢>0.6</年齢>
      </ユーザー>
    </users>
  </body>
</html>

強調部分は、さっきの「ユーザーリスト」です。明らかにXHTMLの語彙ではありませんね。しかし、users以下でデフォルト名前空間がユーザーリストのそれになっていることにより、この部分はXHTMLの語彙として使われているわけではないから、これでもXHTMLとして問題ありません。

ただ、XHTML以外の自分が勝手に作った要素をブラウザは当然知りませんから、そこにそういうタグがあってそういう構造をしていることは認識できても、それがどういう意味なのかは分かってくれません。だから、気を利かせてリストっぽく描画してくれたりはしません。描画をいい感じにするにはやはりCSSを使います。実はCSSでも名前空間を扱うことができますので、気になる人は調べてみましょう。