名前空間
要素のプリフィックス
XML アプリケーションは、一般的に他の XML アプリケーションと機能を共有します
XML は複数の文書と結合したり、データを共有することができるため
XML アプリケーションも、単独ではなく、多くの機能を共有したほうが便利なのです
しかし、他の XML アプリケーションと機能を共有することになれば
当然ながら、要素名の衝突が発生するでしょう
name 要素や title 要素、img 要素などの安易な名前は特に衝突する可能性が高いでしょう
だからといって、誰も使わないようなユニークな名前のタグばかりを使うと
本来の要素の意味を連想できない、非常に読みづらい文書になってしまいます
そこで、名前空間と呼ばれる機能を使うことによってこの問題を解決します
名前空間とは、そもそもオブジェクト指向型プログラミング言語などで用いられる技術で
識別子の前に、特有のプリフィックスを付けることによって名前の衝突を避けるというものです
XML の名前空間は、プログラム言語のそれとは異なる部分がありますが、思想は同じです
おそらく、これを読んでいる貴方と同姓同名の人は、少なくとも数人はいるでしょう
しかし、郵便物は問題なく貴方に届けられているはずです
これは、あなたの名前の前に 国:都道府県:市町村:番地 名前空間があるからです
名前空間を用いるには、それと適応する要素に対し
xmlns:prefix 属性を用いて定義します
prefix には、その名前空間に適応する任意のプリフィックスを指定してください
<prefix:要素名 xmlns:prefix="URI">
属性値には、名前空間となる URI を指定します
なぜ URI を使うのかというと、URI はまさに、世界レベルで一意な文字列だからです
名前空間に指定する URI は、意味のあるものでなくてもかまいません
そのアドレスにどのようなファイルがあるかを保証するようなものではありません
しかし、できることならば、名前空間に関連した文書を置いておくと良いかもしれません
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<kitty:object xmlns:kitty = "http://black.sakura.ne.jp/~third/">
<kitty:title>Kitty on your lap</kitty:title>
</kitty:object>
サンプルを見る
これで、この文書のルート要素 kitty:object 以下は kitty 名前空間となります
名前空間を採用することによって、他の XML ファイルなどを結合させた時
同名の要素でも異なる要素であると認識させることができます
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<kitty:object xmlns:kitty = "http://black.sakura.ne.jp/~third/">
<kitty:title>Kitty on your lap</kitty:title>
<doc:document xmlns:doc = "http://black.sakura.ne.jp/~third/xml/">
<doc:title>Magical nyan nyan TARUTO</doc:title>
</doc:document>
</kitty:object>
サンプルを見る
この文書には title という同名の要素が二つあります
一つは object 要素の子要素の title、もう一つは document 要素の子要素の title です
しかし、それらは名前空間が異なるので、異なる要素であることをパーサは認識できます
XML では複数の XML 文書を結合させることができるため
ひょっとしたら、document 要素は他の XML 文書のルート要素なのかもしれません
しかし、上のように名前空間が異なっていれば、要素名の衝突は問題ありません
また、一つの要素に複数の名前空間を割り当てることも可能です
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<kitty:object xmlns:kitty = "http://black.sakura.ne.jp/~third/"
xmlns:doc = "http://black.sakura.ne.jp/~third/xml/">
<kitty:title>Kitty on your lap</kitty:title>
<doc:document>
<doc:title>Magical nyan nyan TARUTO</doc:title>
</doc:document>
</kitty:object>
サンプルを見る
この文書の object 要素は、kitty と doc 名前空間を包括しています
ところで、プリフィックスが衝突してしまった場合はどうなるのでしょう
要素名の衝突を避けるためのプリフィックスですが、これが衝突することもあります
実は、このようなことが発生するとプリフィックスの再定義が発生します
プリフィックスが再定義された場合、その要素内は新しい名前空間が割り当てられます
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<kitty:object xmlns:kitty = "http://black.sakura.ne.jp/~third/">
<kitty:title>Kitty on your lap</kitty:title>
<kitty:document xmlns:kitty = "http://black.sakura.ne.jp/~third/xml/">
<kitty:title>Magical nyan nyan TARUTO</kitty:title>
</kitty:document>
</kitty:object>
document 要素は名前空間プリフィックス kitty を再定義しています
そのため、この要素以下は新しい名前空間として認識されます
ただし、一般的にプリフィックスの再定義を明示的に行ってはいけません
プリフィックスの再定義は、異なる XML アプリケーションを結合させた時に
たまたま、プリフィックスの名前が衝突した時に効果が暗黙的に現れるものです
上の文書の様に、明示的な再定義をしたところで、可読性の低い文書を作るだけでしょう
デフォルト名前空間
あなたが作成した XML アプリケーションは、あなたが望まなくても
それを公開しているのならば、他の XML 文書と結合される可能性があります
そのため、ルート要素は何らかの名前空間に所属させるべきなのは言うまでもありませんが
全ての子要素に、わざわざプリフィックスを挿入するのは非常に面倒です
そこで、このように単一の名前空間であることがハッキリしている場合
デフォルト名前空間を用いることで
子要素にプリフィックスを付けることを省略し、生産性を上げられます
デフォルト名前空間を用いる方法は簡単で、プリフィックスを持たない名前空間を宣言します
すなわち xmlns 属性でプリフィックスを指定せずに URI だけを指定します
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<object xmlns="http://black.sakura.ne.jp/~third/">
<head>
<title>Kitty on your lap</title>
</head>
<document>
<text>Kitty on your lap</text>
</document>
</object>
この文書の object 要素は、デフォルト名前空間を持ちます
そのため、object 要素内の子要素は、自動的に名前空間が割り当てられます
こうすれば、わざわざプリフィックスを明示的に指定する必要はありません
ただし、複数の名前空間を割り当てる場合、デフォルトにできるのは1つだけです
名前空間の属性
属性は、要素に属する情報なので基本的に名前空間は必要ありません
そのため、名前空間を指定しなくても属性は成り立ちますが
必要であれば、明示的に名前空間をアピールしても問題はないでしょう
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<kitty:object xmlns:kitty ="http://black.sakura.ne.jp/~third/"
kitty:title="Kitty on your lap"
kitty:copyright="Leon Akasaka">
</kitty:object>
通常は、このような書き方をする必要はありません
しかし、XML は2つの異なる XML アプリケーションの属性を結合させることもできます
もし、結合した属性の名前が偶然にも衝突した場合、名前空間を用います
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<kitty:object xmlns:kitty = "http://black.sakura.ne.jp/~third/"
xmlns:kitten = "http://black.sakura.ne.jp/~third/xml/"
kitty:title="Kitty on your lap"
kitten:title="Tokyo mew mew">
</kitty:object>
サンプルを見る
この文書の object 要素は、kitty:title と kitten:title 属性を持っています
属性名は同じですが、名前空間が異なるため問題ではありません