連載

.NETで簡単XML

第1回 XML超入門

株式会社ピーデー 川俣 晶
2003/02/13

Page1 Page2 Page3 Page4

名前空間

 さて、ここまでの解説で、XML文書の中でも整形式のXML文書と呼ばれるもののかなりの部分を読むことが可能になったはずである。そういう目で、最初に紹介したVS.NETで作成したプロジェクトに含まれる拡張子が「.resx」のファイルをもう一度眺めてみよう。

<?xml version="1.0" encoding="utf-8" ?>
<root>
    <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
        <xsd:element name="root" msdata:IsDataSet="true">
            <xsd:complexType>
(以下略)
拡張子が「.resx」のファイル

 これは、リソースを記述するためのXMLベースのファイルの1つである。リソースを記述するにはXMLではない形式も存在するが、XML形式の方が内容を確認したり、内容を書き換えたりする場合に使い勝手がよいだろう。

 さて、最初に出現する要素(文書要素)はrootという名前であることが分かる。そして、root要素の最初の子要素は、xsd:schemaという名前の要素のように見える。しかし、.resxファイル形式のリソースについての説明を調べても、xsd:schemaという名前の要素の説明は見あたらないだろう。それもそのはず、これは「XML Schema」という、リソースとは縁もゆかりもないXMLのスキーマ言語のschema要素なのである。

 どうして、無関係の言語の要素が入り込んでいるのだろうか。それは、このリソースファイルの正しい書き方に関するルール(つまりスキーマ)が、このリソースファイル自身の中に書き込まれているという事情による。つまり、このXML文書内には、リソースとリソースのスキーマの両方が同居しているわけである。スキーマが含まれることで、うっかり手動で誤った書き換えを行った場合、それを検出する手がかりとなる。しかし、要素や属性の配列方法のルールを記述するために、すでに世の中にはXMLのスキーマ言語というものがあり、同じ機能をもう一度要素や属性に定義するのは無駄な手間である。そこで、1つのXML文書に複数の言語の要素や属性を混在させるということが行われる。さらにこれを進めれば、言語を構成する部品として要素や属性を定義することも行われる。プログラムのモジュール化と同じように、XMLでもモジュール化が行われているわけである。

 複数の言語の要素を1つのXML文書で混用すると問題になるのが、要素などの名前が偶然一致してしまうことである。nameのような、ありふれた名前を要素名で使えば、衝突が起こるのは必然である。例えば、商品情報記述言語を作ってname要素が商品名を記述するために使用されているとき、これとは別個に作った顧客情報記述言語では、name要素が人名を記述するために使用しているかもしれない。ある日、この2つの言語の要素を同時に使うXML文書を使う必要に迫られたとき、けっこう困った事態になる。このXML文書を読み込むプログラムを記述するにあたって、name要素が読み込まれた場合に商品名と解釈すべきか、人名と解釈すべきか。ほかに何も付加情報がなければ判定不可能となり、プログラムが記述できないことになる。

 このような問題を回避するために、XMLでは名前空間というものを用意している。これはプログラミングの世界にある名前空間と類似のものと考えてもよいだろう。例えば、.NET Frameworkの世界でもクラス名の衝突という危険があり、これを回避するために名前空間という機能が存在している。しかし、.NET Frameworkの名前空間と、XMLの名前空間は全く別個のものである。この例では、リソース記述言語の要素は名前空間を持っていないが、XML Schemaの要素はhttp://www.w3.org/2001/XMLSchemaという名前空間に属している。本当は、将来的にどんな言語間で混用が起こるか分からないので、どんな言語にも名前空間を付けておいた方がよいのだが、リソース記述言語はそうなっていないようである。

 さてここからが重要な点である。XMLの名前空間名はURIとして記述する。URIとして記述するが、URIは単なる識別のための文字列であって、特定のリソースを指定するものではない。例えば、http://www.w3.org/2001/XMLSchemaが名前空間URIであるとしても、そのURIにアクセスして何かの情報が取得可能でなければならない、というわけではない。では、いったいなぜURIを使うのか。それは全世界でユニークな名前が容易に作成可能だからである。多くの企業、団体はすでにドメイン名を持っていて、そのドメイン名の下の名前をどう使うかは自由である。ほかの企業が勝手にそこに別の名前を定義したりはしない。個人であっても、ISPより提供されたWebサイト作成用のURIの下は独占的に使用でき、他人が勝手に使うことはない。つまり、ほかのだれも絶対に使うことがない名前を容易に得ることができるわけである。

 以上の話をまとめると、xsd:schemaと記述された要素は、http://www.w3.org/2001/XMLSchemaという名前空間URIに属するschemaという名前の要素である、ということである。しかし、どうしてxsd:schemaがhttp://www.w3.org/2001/XMLSchemaに対応すると分かるのだろうか。そもそもxsdとは何だろうか?

 このxsdという文字列は、名前空間の接頭辞と呼ばれるものである。接頭辞の付いた名前を記述する際には、“:”(コロン)で区切って、手前に接頭辞、後に要素名や属性名を記述する。もし、接頭辞を使わないとすれば、http://www.w3.org/2001/XMLSchemaという名前空間URIに属するschemaという名前の要素を記述するために、http://www.w3.org/2001/XMLSchema:schemaと書くことになり、あまりに長くなりすぎる。そこで、接頭辞を使う有効性が生じるわけである。接頭辞は、属性を使って定義する。ここでは、schema要素に付加されたxmlns:xsd="http://www.w3.org/2001/XMLSchema"という属性が接頭辞を定義している。「xmlns:接頭辞名」という書式の属性名は、接頭辞を定義する働きがある。その結果、この属性は、xsdという接頭辞は、http://www.w3.org/2001/XMLSchemaという名前空間に対応すると定義づけているわけである。そして、接頭辞は、この属性を含む要素自身とその子、孫、子孫に及ぶ。だから、xsd:schemaと記述した開始タグ自身の中で、接頭辞xsdを定義しても問題ないのである。

 さて、接頭辞が付かない要素に名前空間を対応づける方法もある。以下はそれを記述した例である。

<?xml version="1.0" encoding="utf-8" ?>
<a xmlns="http://sample">
  <b/>
  <c/>
</a>
デフォルト名前空間

 xmlns="http://sample"という属性が、「デフォルト名前空間はhttp://sampleという名前空間URIに対応する」という意図を表現している。デフォルト名前空間は接頭辞が付かない要素に適用されるので、この例では、a要素、b要素、c要素は、「http://sample」という名前空間URIに属していると見なされるのである。

 さて、次は属性に接頭辞が付かない場合についての説明である。接頭辞が付かない属性は、接頭辞が付かない要素とは扱いが異なる。以下のXML文書を見ていただきたい。

<?xml version="1.0" encoding="utf-8" ?>
<a b="sample" xmlns="http://sample" />
接頭辞が付かない属性

 xmlns="http://sample"という属性の効力は、当然a要素に及ぶので、a要素の名前空間URIはhttp://sampleとなる。しかし、属性にデフォルト名前空間の効力は及ばないため、b="sample"という属性は名前空間が指定されていない名前空間なしという状態になる。属性は要素に付くものなので、名前空間が指定されていない属性であっても、名前空間が指定された要素に付いていれば、要素の名前空間のうち、と考えることもできるので、これでも実用上の問題はない。もし、属性の名前空間も指定したければ接頭辞を使えばよい。例えば、以下のように記述することができる。

<?xml version="1.0" encoding="utf-8" ?>
<p:a p:b="sample" xmlns:p="http://sample" />
接頭辞で属性の名前空間を指定する

 こうすれば要素bは間違いなくhttp://sampleという名前空間URIに属する。しかし、属性に名前空間接頭辞を付けることは多くはない。

 なお、先ほど示した拡張子「.resx」のファイルには、xmlns=""という属性が見えるが、これはデフォルト名前空間を、名前空間なしという状態に設定するという意図を記述したものである。空文字列は、名前空間なしに対応する。

次回予告

 次回は、シンプルにXmlReader/XmlWriterクラスを使ったXML文書の読み書きを行う方法を解説してみたいと考えている。いよいよ、C#とVisual Basic .NETのサンプルソース付きの解説に入って行く予定である。End of Article


 INDEX
  .NETで簡単XML
  第1回 XML超入門
    1.プログラマーにとって重要度を増すXML
    2.簡単なXML文書
    3.ネストする要素、属性、空要素、コメント、XML宣言
  4.XMLにおける名前空間
 
インデックス・ページヘ  「連載 :.NETで簡単XML」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間