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についての)「語彙」などと呼ぶことがあります。

上のaaaとbbbのサンプルでは、2種類の語彙が混在していることになりますね。

名前空間の実体

実はここまで、「aaaに属する」という言い方はしても「aaaが名前空間である」とは言っていません。実は、aaa自体は名前空間とはまた少し違うものなのです。

どういうことかというと、ここで「xmlns:aaa」という属性が絡んできます。

タグ名の前につく「aaa」などを名前空間接頭辞といいます。xmlns:aaaは、

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

という書き方で任意の要素の属性として書く特殊な属性です。こうして書くと、その接頭辞とURIが結びつきます。つまり、今回の場合、aaaという接頭辞がURIと結びついて、そのURIを表していたということです。aaaの場合、「http://example.com/aaa」というURIですね。

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

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

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

名前空間の意味

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

名前空間に意味を持たせるとは、ある書き方(語彙)とある名前空間を結びつけるということです。例えば、あなたがユーザーリストの書き方を考えだして使ったとします。前回の

<?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」とこれらの語彙が結びついたことになります。「http://example.com/users」という名前空間が、これらの語彙を表すのです(実際はこのようにexample.comは使わず、例えば自分のサイトのURLを使ったりしましょう)。

このように結びつけることが何の役に立つのかというと、例えば他の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タグにxmlns:users属性がありますが、ここで作った名前空間接頭辞(今回の場合はusers)は、その要素以下(その要素とその子孫)で有効になります。

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

ここで使うURIですが、基本的に、同じURI(同じ名前空間)なら同じ語彙です。なるべく重複しないようにするのはそのためです。やはり重複しにくいのは自分のサイトのURLでしょう。まさか別の関係ない人が他の人のサイトのURLを使うということもないと思います。

また、このようにいろいろな文書で使われる場合にどのURIに統一すればいいかですが、基本的に一番最初にその語彙を作って使ったときに何という名前空間に属するか決めることでしょう。そうしたらそれに従えばいいのです。

デフォルト名前空間

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

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

<?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の文法(ルート要素はhtmlで、その下にはheadとbodyがあって…)もひとつの語彙であるとみなすことができます。

そこで、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を使うことのさらなる利点が見えてきます。XHTMLの語彙は決まった名前空間に属していなければいけませんでしたが、実は、他の名前空間に属していれば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以外の自分が勝手に作った語彙をブラウザは当然知りませんから、そこにそういうタグがあってそういう構造をしていることは認識できても、それがユーザーリストであることを認識したりはしてくれません。だから、気を利かせてリストっぽく描画してくれたりはしません(スタイルシートでうまく描画させることは可能です)。

次回からは、このようなXHTMLなどの扱い方を解説します。