第1回
XML名前空間の落とし穴

コンピュータ科学で一般に使われている名前空間と、XML名前空間はやや異なる概念だ。XML名前空間は内部構造を持つことに注意しよう。今回はこうした、名前空間仕様の中で誤解されやすいポイントを選んで解説する。

■話題 XML名前空間
■程度 B (より詳細に理解したい人を対象とする)
■目的 仕様の解説
この連載をはじめてお読みになる方は、「XML深層探求について」をご覧ください。

檜山正幸
2000/7/5


1. はじめに
 目次

 1. はじめに
 2. お約束(用語、記法など)
 3. 名前空間の内部構造
 4. タグによるフルネームの表現法
 5. コロンの解釈と使用法
 6. まとめ
 

 XML名前空間を話題にしよう。ただし、名前空間に関するひととおりの知識があることを仮定する。XML名前空間については、原仕様「Namespaces in XML」日本語訳はJIS TR X 0023:1999)と、James Clark氏による短 くて分かりやすい解説 「XML Namespaces」が、標準的な参考文献である。

 名前空間は非常に重要である。今後、XMLベースのマークアップ言語は、必ず名前空間を使うべきだ。可能ならば、既存のマークアップ言語も、名前空間への適合を行うのがよい。名前空間を無視した技術や仕様は、XMLとWebの機能性と利便性を大きく損なうことになる。今回は、名前空間仕様の中で、誤解されやすいポイントを選んで解説する。

Note: 個人的な好悪の感情からいうと、XML名前空間の仕様は好きになれない。属性の形を借りるという宣言構文に、いまだに違和感を感じる。が、だからといってXML名前空間の重要性が減ずるわけではない。


2. お約束(用語、記法など)

 まず、言葉使いに関する注意を述べる。この記事では、「要素型」「要素型名」(「要素名」) という言葉を避けている。それには理由があるのだが、いまここでは触れない(いずれ、このシリーズで明らかにするつもりだ)。とりあえず、原仕様や他の記事などで「要素型」「要素(型)名」と呼ばれているものが、ここでは「タグ」「タグ名」になっていることに注意してほしい。

 次に、説明のための記法を導入しよう。タグ名のフルネームを表すために、James Clark氏の解説にならって

{URI}tagname

という書き方を使う。例えば、

{http://www.w3.org/1999/xhtml}p

という書き方は、XHTMLのpタグ(の名前)を表す。よって、

<p xmlns="http://www.w3.org/1999/xhtml">

は、意味的には、

<{http://www.w3.org/1999/xhtml}p>

ということになる。もちろん、こんな書き方は、XML構文上は許されない。あくまでも説明用だ。また、属性名は{URI}tagname#attnameの形で書こう。すると例えば、

<p xmlns="http://www.w3.org/1999/xhtml" id="p12">

に対して、タグ名も属性名もフルネームに展開すると、 次のように書ける。

<{http://www.w3.org/1999/xhtml}p
    {http://www.w3.org/1999/xhtml}p#id="p12">

Note: フルネームという言い方は名前空間仕様には出てこない。付録Aには、expanded element type、expanded attribute nameという言葉が出てくるが、これが、この記事のフルネームにあたる。一方、James Clark氏はuniversal nameという言葉を導入している。


3. 名前空間の内部構造

 「名前空間」という言葉は誤解を招きやすい。コンピュータ科学で一般に使われている名前空間と、XML名前空間はやや異なる概念だからだ。XML名前空間は内部構造を持つことに注意しよう(名前空間仕様の付録A 「The Internal Structure of XML Namespaces」で説明されている)。1つのXML名前空間は、区画(partition)と呼ばれる小部屋に分割される。区画には次の3種がある。

  1. タグ名の区画 (1つ)
  2. 大域属性名の区画 (1つ)
  3. タグごとの属性名の区画 (複数)
Note: 原仕様では、3種の区画を次のように呼んでいる。
1. The All Element Types Partition
2. The Global Attribute Partition
3. The Per-Element-Type Partitions

 次の例で説明しよう。

<my:foo xmlns:my="http://mySite.ourDomain/xmlns/myOwnML"
    type="mine" my:status="draft">

 タグ名fooは、http://mySite.ourDomain/xmlns/myOwnMLで識別される名前空間のタグ名区画に属する。そのフルネームは先に約束した記法により

{http://mySite.ourDomain/xmlns/myOwnML}foo

と書ける。属性名typeは、タグ{http://mySite.ourDomain/xmlns/myOwnML}fooに固有の属性と解釈されるから、タグごとの属性名区画に属し、そのフルネームは

{http://mySite.ourDomain/xmlns/myOwnML}foo#type

である。

 一方、接頭辞myで修飾された属性statusは、この名前空間に対して大域的となる。そのフルネームは

{http://mySite.ourDomain/xmlns/myOwnML}#status

となる。

 フルネームの形からどの区画に属する名前かを判断することができる。

  1. {URI}tagnameなら、タグ名区画に属す。
  2. {URI}#attnameなら、大域属性名区画に属す。
  3. {URI]tagname#attnameなら、タグごとの属性名区画に属す。

■図1 名前空間の区画

 名前空間の構造を象徴的に図示するなら、図1のようになる。横軸はタグ名の区画を表す。横軸の上に乗っている点(黒丸)は、個々のタグ名である。一番左に描かれている縦軸は大域的な属性名の区画、横軸上の点から突き出ている縦線は、タグごとの属性名の区画である。それぞれの区画において、仮に最初の3つの名前はfoo,bar,bazであるとした。

 この図から見てとれるように、同じfooという名前が1つの名前空間内に(可能性として)無限個存在する。タグ名foo、 大域属性名foo、タグfooの属性名foo、タグbarの属性名foo、タグbazの属性名foo……といった具合である。


Note: 先の図では、直線上に無限個の名前が離散的に並んでいた。これは、単なる比喩的な図ではなく、実際に名前を並べあげることが可能である。いま、3文字「a, b, c」からなる文字列を考えてみよう。まず、長さ1の文字列(文字そのものと同一視できる)をアルファベット順に、a, b, cと並べる。次に長さ2の文字列を辞書式の順序で並べると、aa, ab, ac, ba, bb, bc, ca, cb, ccとなる。以下同様に、長さと辞書式順序を併用して、いくらでも並べることができる。

XMLで使える名前は、Unicode文字からなる文字列で若干の条件を満たすものである。Unicode文字は数多いが、所詮は有限個しかない。長さ1の名前、長さ2の名前、と並べることはできる。機械的な辞書式順序は、文字番号順序をもとに導入すればよい。


4. タグによるフルネームの表現法

 名前空間仕様の付録Aでは、完全に展開(expand)されたタグ名(要素型名)、属性名を<ExpEType/><ExpAName/>というタグを使って表現している。タグ名、属性名を表す方法として、この付録Aと似た方法もつかえる。つまり、フルネームをXML形式で表現してみるのだ。

1.{URI}tagnameは、次のように表す。

<tagName nsURI="URI" localName="tagname" />


2.{URI}#attnameは、次のように表す。

<attName nsURI="URI" localName="attname"/>


3. {URI}tagname#attnameは、次のように表す。

<attName nsURI="URI" tagLocalName="tagname"
    localName="attname"/>

 この表現法を使うと、

<my:foo xmlns:my="http://mySite.ourDomain/xmlns/myOwnML"     type="mine" my:status="draft">

は次のように解釈できる。

<tag>
  <tagName nsURI="http://mySite.ourDomain/xmlns/myOwnML"
      localName="foo"/>
  <attribute>
    <attName nsURI="http://mySite.ourDomain/xmlns/myOwnML"
        tagLocalName="foo" localName="type" />
    <value>mine</value>
  </attribute>
  <attribute>
    <attName nsURI="http://mySite.ourDomain/xmlns/myOwnML"
      localName="status" />
    <value>draft</value>
  </attribute>
</tag>

サンプル1で実際のXML文書を見ることができる。

 どの名前空間にも属さない名前は、nsURIの値が""であるとする。

<foo type="mine" status="draft"> (事前のxmlns宣言はないとする)

上記なら、次のように展開される。

<tag>
  <tagName nsURI=""
      localName="foo"/>
  <attribute>
    <attName nsURI=""
        tagLocalName="foo" localName="type" />
    <value>mine</value>
  </attribute>
  <attribute>
    <attName nsURI=""
        tagLocalName="foo" localName="status" />
    <value>draft</value>
  </attribute>
</tag>

サンプル2で実際のXML文書を見ることができる。

Note: タグのフルネームへの展開結果の構文は、次のDTDで規定される。
<!ENTITY % URI "CDATA">
<!ENTITY % Name "NMTOKEN">

<!ELEMENT tag (tagName, attribute*)>

<!ELEMENT tagName EMPTY>
<!ATTLIST tagName     
     nsURI %URI; #REQUIRED
     localName %Name; #REQUIRED >

<!ELEMENT attribute (attName, value)>

<!ELEMENT attName EMPTY>
<!ATTLIST attName
     nsURI %URI; #REQUIRED
     tagLocalName %Name; #IMPLIED
     localName %Name; #REQUIRED >

<!ELEMENT value (#PCDATA)>
%URI;などでデータ型を暗示した。ただし、URIとして空文字列は許されないから、正確には、「URI + 空文字列」がnsURIの値の範囲である。名前空間仕様の付録Aでは、空文字列を使う代わりにURIを記述しない方法をとっている。

Note: 名前空間仕様では、namespace name, local partという言葉が使われていたが、DOM2仕様では、namespace URI、local name となっている。私は、(どちらかといえば) DOM2に従っている。


5. コロンの解釈と使用法

 「XML1.0」(日本語訳は JIS TR X 0008:1998)では、コロンは名前文字に含まれる。つまり、コロンは名前のなかに、どこにでも何個でも入れてよいわけだ。例えば、:a::b:cはXML1.0と照合して正しい名前である。しかし、名前空間仕様で、この定義は修正された。いまやコロンは、一般の名前文字とはまったく異なる特殊文字として扱われる。コロンの役割は、名前空間接頭辞とローカル名を区切ることである。

Note: 名前の定義をXML1.0から引用すると、
NameChar ::= Letter | Digit | '.' | '-' | '_' | ':'
     | CombiningChar | Extender
Name ::= (Letter | '_' | ':') (NameChar)*
ただし、コロンに関しては注意を要する旨の注釈が付けられている。

 コロンを特別扱いするなら、通常の名前にコロンを含めることはできない。つまり、実体名、PIターゲット名、記法名などにコロンを入れることはできないことになる。また、ID、IDREF(S)、ENTITY(IES)、NOTATIONとして宣言された属性値にもコロンを入れられない。例えば、XMLスタイルシート宣言(Associating Style Sheets with XML documents)が<?xml:stylesheet ...?>ではなく、<?xml-stylesheet ...?>なのは、PIターゲットにコロンを含めることができないからである。

 名前空間仕様からみたときは、次のような記述は間違いである。

  • &my:name;
  • <?serverside:include href="foo.html"?>
  • <p id="chap1:sec3:p5">idはIDと宣言されているとする)

たまに、上のような誤ったコロンの使用を見かける。注意しよう。



6. まとめ

 今回扱った内容をまとめると、次のようになる。

  1. XML名前空間は内部構造を持つ。1つの名前空間は、タグ名区画、大域属性名区画、(複数の)タグごとの属性名区画に分けられる。
  2. タグ名、属性名をフルネームに展開してみると、名前空間の構造と使用法を理解しやすい。
  3. タグ名と属性名に限って、コロンをたかだか1個だけ入れることができる。ほかの種類の名前(実体名、PIターゲット名、記法名、名前を要求する属性値)にはコロンを入れられない。

今回のリンク

履歴
2000/7/5 (公開)
2000/7/6 (リンクを日本規格協会の標準情報に変更)
2000/7/6 (リンクの説明書式をJIS TRに統一)


「XML深層探求」



XML & SOA フォーラム 新着記事
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

HTML5+UX 記事ランキング

本日月間