XMLを用いて新しい言語を作る場合、好き勝手にタグを定義したり、構造を定義していたのでは何の役にも立たない言語になりかねない。言語を作るときには、一度きりで使い捨てになる言語ではなく、再利用のことをあらかじめ考えた設計が求められる。では、再利用性の高い言語とはどんなものだろうか。今回はそのことについて解説しよう。
よく使われるものを、パターン化し、規格化し、再利用するのは、どんな分野でも常識的に使われるテクニックである。
例えば、デジタル回路を設計する場合には、AND, OR, NOTといった基本的な演算機能を持った部品を組み合わせる。しかし、実現する機能が変われば回路は大幅に変化してしまい、設計図は引き直しとなる。例えば、外見が同じに見える電卓を開発する場合でも、機能が異なればまた回路をゼロから描き直すことになる。これでは無駄が多い。
そこで、機能を実現する作業手順をハードウェアから切り離す構造が考案された。このアイデアによって、まったく同じハードウェアであっても作業手順を入れ替えることによって、異なる機能が実現できることになる。これによって、ハードウェアは特定のモデルに限定されず、再利用可能な部品へと進化したといえる。そして、この再利用を実現するチップこそ、現在のパソコンで使用されているCPUの直接の祖先にあたる部品になる。そういう意味で、パソコンと再利用という概念は切っても切れないものがあるといえる。
ソフトウェアの分野でも、再利用は重要である。1980年代ぐらいまでは、COBOLプログラマは容易に機械的に自動生成できるようなパターン化されたコードを、毎度手で書いていた、という話もある。これは情報投資は聖域と考えられていた幸運な時代にのみ通用する話であろう。全体的な流れとしてソフトウェア開発の歴史を見れば、ソフトウェアの断片に再利用の価値があることを積極的に認めて、それをうまく活用する方法を模索する話題に事欠かない。
例えば、最も原始的な構造の1つである「サブルーチン」と呼ばれるものは、1つのプログラムで繰り返し利用される部分を抽出したものといえる。さらに、再利用可能な部品をライブラリとして整備したり、オブジェクト指向においては最初から再利用されることを前提としてクラスを設計することを原則とするほどである。
ところが、SGMLなどの構造化文書の世界では、再利用に関する認識は遅れていた。それはDTDの仕様を見れば一目瞭然である。DTDは設計時にすべての要素や属性が明らかになっていることが前提となっている。設計時にまだ決まっていない別の言語の要素や属性と併用することを、適切に表現する能力を持っていない。
しかし、電子商取引など、現実世界の幅広い分野で利用しようとすると、膨大な数の言語を作り出す必要が生じる。その際に、それぞれの言語をゼロからいちいち作るのでは非効率的すぎる。言語を別々に作る非効率は、言語仕様作成の手間だけでなく、もっと広範囲に影響する。複数の言語の中の共通部分を、再利用可能な断片として規定することができれば、それを処理するソフトウェアも再利用可能なプログラム部品として作成できることを意味する。つまり、全体として効率よくシステムを構築し、運用していくためには、再利用性を強く意識する必要がでてくる。従って、XMLの世界でも、「たまたま再利用が有益なときに再利用を意識して言語を作る」のではなく、「どんな言語であろうと、再利用を意識する」ということが求められているのだ。
ここで、実際に再利用を前提として作られた言語の例を見てみよう。XKP GAIJI交換仕様書 第1.0版に含まれる拡張可能なGAIJI参照言語(Extensible GAIJI Reference)(以下XGRと記述する)という言語をここでは取り上げてみたい。
XGRは、XML文書の中に、画像データを指し示す情報を埋め込む。ただし、HTMLのimg要素のように、直接画像データを指定するのではなく、もっと抽象的な名前を指定する。登録されている名前には、現在8万文字以上の文字を収録する今昔文字鏡の収録文字に対応するものがある。XGRを用いることで、ある特定の文字の形を、画像データとして直接指定することができるわけで、「ちょっと普通と違う私の名前の漢字」を明確に指定する、といった機能を実現できる。
ここでのアイデアのポイントは、文字を文字コードで示すのではなく、画像データとして参照することにある。つまり、XGRは「文字」を扱う言語ではなく、「画像データ」を扱う言語なのである。これにより、(文字コードで文字を指定するときに発生する)フォントデザインの違いによって微妙に違う別の文字を、画面やプリンタから出力してしまう危険から解放される。ただ単にHTMLのimg要素のような画像ファイルを直接指定してしまう方法だと、別ファイルを示しただけなので、表示したい文字と同じ画像を示しているのかどうか判断が付かなくなってしまう。そこで画像データに名前を付けて、それを使って参照するというのが、XGRならではの特徴だ。
さて、前置きはこのぐらいにして、XGRがどのように再利用を意識した言語であるかを見てみよう。
まず、このXGRは、単体でXML文書を記述できないことを指摘したい。つまり、通常の文書を記述するために必要な要素や属性を、すべて何も規定していない。段落を示す要素すらない。ある意味で驚くべき大胆さといえるが、最初から再利用を前提とした言語なら当然の選択といえる。段落などを記述する能力を持った言語はすでに世の中に多数あるわけで、すでにあるものはそれを再利用するのが、再利用的な態度である。
XGRに存在するのは、わずかに、たった1個の要素と、それに付随するたった1個の属性である。具体的なDTDの定義は以下のようになっている。
<!ELEMENT gaiji ANY> <!ATTLIST gaiji name CDATA #REQUIRED>
ただし、この定義を読む場合は注意しなければならない。それは、gaiji要素がどのような親要素の下にくるか、gaiji要素の子要素に何がくるかは、XGR側ではまったく関知していないということだ。これは併用する言語のつごう次第で何がくるか分からないということだ。
この言語が具体的なXML文書の中でどのように使われるかピンとこない人もいると思うので、上記仕様書からXHTMLとXGRを併用したサンプルを以下に示そう。
<?xml version="1.0"?> <!-- 別掲のスタイルシートを指定している --> <!-- スタイルシートを理解するWebブラウザで見ればGAIJIは解釈され表示される --> <?xml-stylesheet type="text/xsl" href="xhtmlplusgaiji001.xsl"?> <!-- デフォルトの名前空間をXHTMLに。プリフィクスxgrは拡張可能なGAIJI参照言語に --> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:xgr="http://www.xkp.or.jp/GAIJI/Reference"> <head> <title>GAIJI Sample 001</title> </head> <body> <h1>GAIJI Sample 001</h1> <!-- xgr:gaiji 要素がGAIJIを指定している。要素の内容はGAIJIが処理できないときのための情報 --> <p>私の名前は<xgr:gaiji xgr:name="MOJIKYO.65132">アカ【文字鏡番号65132】</xgr:gaiji>星太郎です。</p> </body> </html>
この例では、XHTMLのp要素の子要素として、XGRのgaiji要素が記述されている。そして、gaiji要素の子としては、XHTMLの通常のテキストで内容に関する説明が記述されている。XGRでは画像データにアクセスできない場合には、gaiji要素の子を代用として使用すると規定している。しかし、それが文字列であるべきだとは一切規定していない。これが最初のポイントになるので、詳しく説明しよう。
HTMLのimg要素では、画像データを扱えない場合に表示する代替文字列を、alt属性で指定する仕様になっている。これと同じような感覚で考えると、gaiji要素にalt属性を設けて、ここに代替文字列を記述することが適切であるかのように思える。しかし、HTMLとXGRでは、前提が決定的に食い違っている点がある。HTMLでは、扱うデータは基本的に文字列と、GIFやJPEGのようなビットマップと決まっている。もちろん、それ以外のデータも扱えないわけではないが、標準的ではない。そのため、HTMLで画像データが扱えない場合は、文字列で処理するしかない、という結論に至る。しかし、XGRの場合は、どんな言語と併用して使われるか分からない。もしかしたら文字列という概念のないグラフィック言語かもしれない。そのことを考えると、XGRでは、代替文字列は文字列だと決めつけることはできない。そもそも、文字列でないなら代替文字列とはいえないのである。そこで、この情報をこれ以後は「代替表示情報」と呼ぼう。
さて、代替表示情報が画像データである、という状況は具体的にどういうことだろうか。例えば、ベクターグラフィック言語のSVGの中に、XGRを埋め込んで使うことも考えられる。この場合、代替表示情報はSVGで描かれた文字の形であって悪いことは何もない。SVGの曲線データはXMLフラグメントになるが、属性には文字列しか記述することができない。そのため、属性に代替表示情報を記述するという作戦は、この場合にうまく機能しない。属性ではなく、要素の子として記述するようにすれば、文字列だけでなくXMLフラグメントも持たせることができる。
別の角度から考えてみると、文字列を代替表示情報として使う場合でも、詳しい情報を記述したサイトへのリンクを埋め込みたい、といったケースが考えられる。当然のことながら、文字列しか持てない属性ではこのニーズに対応できない。
これらの話から分かるとおり、HTMLのimg要素のようなalt属性を持たせることでは、XGRが想定するニーズには対処できないのである。このように、どんな言語と組み合わされても機能するように考えることが、再利用性の第1のポイントである。
XGRについての説明をさらに進めよう。ここでは、あるRDBのデータを入出力するために以下のような言語があると仮定する。
ルート要素がrecordという名前で、子要素に、fieldという要素を任意の個数持つことができる。fieldの子として文字列を持つことができ、これがデータを示す。field要素にはname属性があり、これがフィールド名を示す。この言語で記述された1個のXML文書が、RDB上のテーブルの1つのレコードの情報を持つとする。
例えば、以下のような文書を記述することができる。
<record> <field name="名前">島大輔</field> <field name="年齢">18</field> <field name="所属">宇宙戦士訓練学校</field> </record>
さて、ここで何やら人名の漢字にうるさい人の分も、データを書かねばならなくなったとする。パソコンに入っているフォントで処理すると、「漢字の形が違う!」と怒り出すので、何とか対処したいと考えたとする。
ここで1つのアイデアは、このレコード記述言語と、前述のXGRを合体させて運用することである。XGRの情報を処理するために、多少システムを拡張する必要は生じるが、XGRで示す画像データにはユニークな名前が付くので、検索も可能になる。これならいけるということで、その人のデータを表す、以下のようなXML文書を書いてみたとしよう。
<record xmlns:xgr="http://www.xkp.or.jp/GAIJI/Reference"> <field name="名前"><xgr:gaiji xgr:name="MOJIKYO.65132">アカ【文字鏡番号65132】</xgr:gaiji>星太郎</field> <field name="年齢">18</field> <field name="所属">宇宙戦士訓練学校</field> </record>
ここまではうまくいくのだが、この次の手順で問題が起きてしまう。このXML文書をRDBに格納しようとしたとき、RDBのフィールドに文字列は入るが、XMLフラグメントは入らない。つまり、gaiji要素や、それに付随するname属性を、そのままRDBに格納することができない。
この問題をどう考えるかは微妙なところである。今ある道具だけを前提にすれば、このような言語の組み合わせはNGということになる。言語の再利用を行うと、要素の階層構造は必然的に深くなるからだ。この場合、RDBと言語の再利用のどちらがより重要か、が選択のポイントである。現時点では、性能面でRDBの使用は外せないというケースも多いと思われるが、言語の再利用に関する強いニーズも厳然と存在する。このジレンマを解決するには、RDBを高性能XMLデータベース置き換えていくしかないだろう。RDBに匹敵するXMLデータベースはまだ存在しないと思われるが、ニーズがある以上、RDBを置き換えられるだけのパワーを持ったXMLデータベースの出現はそう遠い未来のことではないだろう。
データベース論はさておき、実際に言語を作るという観点から見た場合、再利用の制限と可能性に関する考察が必要だといえる。つまり、上記の言語をあくまでRDBへの格納用ととらえるならば、field要素の子に文字列以外の要素を持ってくるような形での言語拡張は不可であると明確にする必要がある。逆に、言語拡張の可能性が必然的なニーズであるならば、RDBへの格納は不可能であり、XMLデータベースの利用が必要であるという提言を発するきっかけとなる。
さて、データを表すこのRDB言語には、もう1点、再利用性という意味で検討を要することがある。ここではフィールド名を示すために、name属性が使用されている。このname属性に対して、何らかの再利用可能な言語を用いた拡張をしたいと思う人が出てきたら、何が起こるだろうか。例えば、フィールド名に難しい漢字がいくつかあるからルビを振りたい、といった拡張が考えられる。しかし、属性にはそれ以上子を持たせることができないため、拡張は不可能ということになる。
ここでさらに考える必要がある。属性の名前とは、単に機械的にフィールドを区別するために付けられた便宜上の名前にすぎないのか。それとも、それは人間にとって読む意義のある文字列なのか。もし、後者であれば、人間に対する表現力を高めるという意味で、さらなる拡張が試みられる可能性がある。しかし、ソフトウェアの内部で使う識別名にすぎないと考えるなら、そのソフトウェアは名前に関するルールを決めているはずである。そのルールから逸脱する名前を付けることは、ただ単に利用不能のデータを作り出してしまうだけのことである。ならば、再利用可能な言語を付け加えて拡張することなど考える必要はないし、もっと突っ込んでいえば、拡張を許す構造にしないことがトラブルを未然に防ぐ手段とさえいえる。
もし、再利用可能な言語が付け加えられて利用されることがあり得るとするならば、属性として記述することは適切ではない。これは要素に変更すべきものだといえる。しかし、何かを付け加えてはならない性格のものであるならば、属性として文字列以外を書けないようにしておくことも、1つの選択である。
どちらを選択するにせよ、決断するには、再利用性ということを十分に意識しなければならない。
XMLで言語を作るときによく出てくるのが、段落や文字の強調といった表現のための機能だ。再利用を前提とした言語設計を行うのであれば、この手のよく出てくる機能は、メジャーな言語から借りてくるとよい。特に、XHTMLに既にある機能は、XHTMLを再利用可能な部品と見なして丸ごと利用してしまうとよい。
そのような設計にしておくと、現実のご利益がある。例えば、XSLTスクリプトを用いて、あるオリジナルな言語から(X)HTMLへ変換する場合、XHTMLの要素はそもそも変換が必要なくなる。変換せずに素通しするには、XSLTではxsl:copy-of要素を用いることで簡単に実現できる。あとは、独自機能だけを(X)HTMLに変換するスクリプトに書けばよいわけで、楽ができる。
これは、決して「(X)HTMLと同じ仕様の要素や属性を定義しておけばよい」ということにならない。あくまで、XHTMLの要素をそのまま持ってきて使う点が重要だ。
つまり、以下の2つは同じとは見なせない。
<?xml version="1.0"?> <myLanguage xmlns="http://myLanguage" xmlns:xhtml="http://www.w3.org/1999/xhtml"> <xhtml:p>はろ〜</xhtml:p> </myLanguage>
<?xml version="1.0"?> <myLanguage xmlns="http://myLanguage"> <p>はろ〜</p> </myLanguage>
このサンプルでは、p要素はXHTMLのp要素と同じものとして処理したいという意図は同じなのだが、p要素に作る名前空間名が異なっている。上の例ではhttp://www.w3.org/1999/xhtmlという名前空間に属するが、下ではhttp://myLanguageという独自言語の名前空間に属している。現在は、HTMLに対応しているWebブラウザにXHTMLをHTMLであるかのように認識させているので、名前空間とは関係なく、結果が表示されるかもしれない。しかし、本格的にXHTML対応してくる次世代のWebブラウザでは、名前空間をきちんと認識するようになるだろう。つまり、名前空間がhttp://www.w3.org/1999/xhtmlに属さない要素は、いくら名前が同じであってもXHTMLの要素と見なしてくれず、エラーになる可能性がある。
前節の例では、XHTMLのp要素が、myLanguage要素の子要素として出現している。当然、XHTMLの規定の中には、p要素がmyLanguage要素の子要素となって良いという規定は存在しない。しかし、再利用という考え方を前提にするなら、作成した要素や属性が、どのような使われ方をするか、あらかじめすべてを予見することはできない。そのことから、複数の言語を混用する場合には、その都合に応じて、ルールを変形させながら利用することも多いと思われる。
しかし、何でもかんでも自由にしてよい、という考え方を取ると山のようなトラブルを抱えることになる。言語と言語を組み合わせる場合には、よく使われる型があり、これに沿って言語を作ったり、使うようにするとよいだろう。
文書系で典型的な型は、要素を、ブロック要素とインライン要素に分類する考え方である。ブロック要素とは、段落など、ページの中で1つのかたまりを構成する要素のことをいう。つまり、最もシンプルなページは、上から下に向かって、ブロックが並んでいる構造を持っているといえる。これに対して、インライン要素は行の中の一部を構成する要素である。文字列の中に挿入される画像や、文字そのものを修飾する強調などの機能がこれに該当する。
再利用を意識して言語を設計する場合は、それぞれの要素がブロック要素かインライン要素かを考えながら作成し、言語を混用するときは、ブロック要素はブロック要素として、インライン要素はインライン要素として使うようにすると、きれいで分かりやすい秩序を導入できる。余談だが、XGRは文書と併用する場合、インライン要素に相当すると考えられる。
文書系以外では、例えばRDB用のデータなら、レコードとフィールド、といった基本分類を設けて整理することができるだろう。
長期的な視野で見ると、名前空間に対応するスキーマ言語は、言語間の関係性も、整理して規定する能力を持つことになる。これらの言語が一般的に使用されるようになれば、まだ別の指針を語ることもできるだろう。
今回は、かなり抽象的で高度な話題になってしまい、読むのに苦労した読者も多いことだと思う。だが、今回の内容は苦労に値するだけの価値がある。つまり、再利用可能な言語というものを使いこなせば、XMLの活用に関する手間と労力が軽減でき、より大きなパワーを発揮させることができるようになるのである。
ここで「より少ない手間で目的を達成しようとは、手抜きか横着か?」と思わないでいただきたい。これはインターネットの持つ、コミュニケーションという性質と密接に関係することである。相互理解を成立させるためには、相互に同じ言語を理解可能でなければならない。しかし、インターネット上のすべての利用者、すべてのコンピュータがあらゆる言語を理解すると期待するのは現実離れしている。少しでもコミュニケーションの可能性を高めるためには、言語の種類は少ない方がよい。しかし、世の中のXMLに対するニーズは多様であり、そう簡単に言語の種類を減らすことはできない。ならば、言語の含まれるボキャブラリを可能なかぎり統一しておき、全体は理解できなくても、一部なら理解できるというレベルは最低でも維持しなければならない。
これは、インターネットが宝の山になるか、ゴミの山になるかというギリギリの選択なのである。仕事熱心だからといって、新しい言語、新しいボキャブラリを生み出し続けることは勧められない。他人から理解されない言語、ボキャブラリはゴミと等価と見なされてしまう可能性が存在するのだ。
さて、次回は趣向を変えて、XML宣言に出てくるstandaloneということは何かを考えてみよう。
それでは次回、また会おう。
Copyright © ITmedia, Inc. All Rights Reserved.