目次


XMLの論考: 第7回

W3C XML SchemaとDocument Type Definitions (DTD) の比較

確かにW3C XML Schemasには優れた点が数多くありますが(訳注:この翻訳では、W3Cによって定義されたXML SchemaをW3C XML Schemaと表し、一般のXMLのスキーマ言語を、XMLスキーマと訳します)、DTDの方が優れている分野も依然として多いのです。そのため、XMLの世界の開発者は日頃から難しい選択に迫られています。こうした選択肢を探査する旅に、出発しましょう。

現状

データ表記形式としてXMLを使用する主な意義は、文書の構造上の要件を指定できることです。要素の中にどんなタイプ (および順序、多重度など) の内容や副要素が現れることができるかについての厳密な規則を指定できます。従来のSGMLの世界では、文書規則を表すのにDTDを使用してきました。実際、正式な仕様であるW3C XML 1.0勧告 もDTDについて定めています。しかしDTDでは不可能なこともあり、これが制限となる場合が少なくありません。DTDの主な限界は、データ型を表す機能の少なさです (たとえば、要素内容がPCDATAでなければならないという指定は可能ですが、nonNegativeInteger とは指定できません)。それに加えて、DTDでは副要素の多重度 (カーディナリティー) を簡単に指定できません。「1つまたは複数」といった簡単な指定はできます。「7つから12までの間」のような指定も確かに可能ではありますが、きわめて冗長または難解になります。

DTDのさまざまな限界に対する解決策として、一部のXMLユーザーたちは、文書の規則を指定する代わりの方法を求めてきました。XML文書の状態をプログラム的に調べることはこれまでも可能でしたが、「一連の正式な規則に従わない文書は妥当でない(invalid) 」といった、より厳格な基準を定めることのできる能力が欲しいのです。W3C XML Schemaは、こうした声に応える主要な仕様の1つです (ただし、スキーマはこれ以外にもあります)。Steven Holzner氏が著書Inside XML の中でXMLスキーマの性格をよく捕らえていますので、それを引用しましょう。

DTDはとても複雑であるため、これまで多くの人がW3Cに対して不満を述べ、よりシンプルなものを求め続けた。W3Cはこれを聞き入れ、この問題に取り組む委員会を設置し、従来のDTDよりもずっと複雑なソリューションを考え出した (199ページ)。

Holzner氏はさらに、W3C XML Schemaはかなり複雑であるものの、数多くの重要な機能を提供するので、多数の妥当性検査規則のクラスで使用する価値があると述べています (この点については、私自身を含めてほとんどのプログラマーが同意するでしょう)。

スキーマの圧倒的普及という目標に向けて、少なくとも2つの基本的かつ概念上の問題が残っています。1つの問題は、2000年12月15日に検討期間が終わったW3C XML Schema勧告候補 は実体 (エンティティー) がないことです。(これはパラメーター実体も定めれていないことを含みます)。(訳注:XML Schemaは、2001年5月3日にW3C勧告になりましたが、この勧告にも、実体の宣言は含まれていません)。2番目の問題は、表現が豊富になったとはいえ、依然としてXMLスキーマで表現できない文書規則が多くあります (妥当性検査の表現を豊富にするためにXSLTの使用が提案されていますが、その他の方法も可能であり、実際に使われています)。言い換えると、スキーマは、DTDがこれまで提供してきた機能をすべて提供するとは限らず、開発者が文書の中に定めたいと思うような追加規則をすべて表現できるわけでもありません。もっと実用的な面から言うと、XMLスキーマを扱うツールはDTDを扱うツールに比べて未熟です (とくに、肝心な妥当性検査に関して)。

XML文書の妥当性検査を取り巻く状況は、まだまだ整備されていません。最終的にどうなっていくか、残念ながら私には予測できません。(どのような状況でDTDを使うのが妥当と思われるかについて、欄外記事「どんな時にDTDを使用すべきか」をご覧ください。)以下では、DTDおよびXMLスキーマが表現できる特定の点について見ていきましょう。

型指定の豊富さ

W3C XML Schemaがその真価を発揮するのは、属性値および要素内容の型制約です。これはDTDの最大の弱点です。XMLスキーマでは、あらかじめ組み込まれた一連の豊富なsimpleType に加えて、正規表現に似た構文を使って独自の新しいsimpleType を派生させることができます。あらかじめ組み込まれた型には、プログラム言語でよく見かけるstringintfloatunsignedLongbyte などが含まれているほか、ほとんどのプログラム言語に元々ないもの、たとえばtimeInstant (日付と時刻)、recurringDate (一年の中での日付)、uriReferencelanguagenonNegativeInteger も含まれます。

DTDでは、たとえばリスト1のように宣言します。

リスト1: DTDで "item" 要素を定義する
<!ELEMENT item (prodName+,USPrice,shipDate?)
<!ATTLIST item partNum CDATA>
<!ELEMENT prodName (#PCDATA)>
<!ELEMENT USPrice (#PCDATA)>
<!ELEMENT shipDate (#PCDATA)>

W3C XML Schemaでは、次のように、より具体的に指定できます (W3C Schema入門書から少し変更)。

リスト2: XMLスキーマで "item" 要素を定義する
<xsd:element name="item">
 <xsd:complexType>
 <xsd:sequence>
 <xsd:element name="prodName" type="xsd:string" maxOccurs="5"/>
 <xsd:element name="USPrice" type="xsd:decimal"/>
 <xsd:element name="shipDate" type="xsd:date" minOccurs="0"/>
 </xsd:sequence>
 <xsd:attribute name="partNum" type="SKU"/>
 </xsd:complexType>
</xsd:element>
<!-- Stock Keeping Unit, a code for identifying products -->
<xsd:simpleType name="SKU">
 <xsd:restriction base="xsd:string">
 <xsd:pattern value="\d{3}-[A-Z]{2}"/>
 </xsd:restriction>
</xsd:simpleType>

コードを表面的に見ると、この要素定義には2つの顕著な特徴があります。1つは、スキーマ自体が、xsd 名前空間をタグに使用する整形式XMLインスタンスだということです (DTDも同じですが、DTDの場合は内容ではなく処理命令のみのXMLインスタンスです)。2番目の点は、(1番目の結果として) スキーマがDTDよりはるかに長いことです。

構文上の特徴のほかにも、上記のスキーマの例にはDTDにない機能がいくつかあります。prodName 型は基本的にどちらの定義も同じですが、スキーマのUSPrice およびshipDate の指定はdecimal 型およびdate 型になっています。これらの要素を持つXMLインスタンスには、テキスト・ファイルとして、何らかのASCII文字 (またはユニコード文字) が要素に入っています。しかし、スキーマを認識するバリデーター (妥当性検証プログラム) は、decimal の要素とdate の要素の中により具体的な文字形式が含まれることを要求します (他の型の場合も同様)。さらに興味深いのは、派生された特化型の属性partNum です。SKU 型はあらかじめ組み込まれた型ではなく、"SKU" 宣言に示される特定パターンに従う文字シーケンスです (具体的には、3桁、ダッシュ、2つの大文字という順番でなければなりません)。なお、SKU を要素型に使用することも可能です。上記のケースでは、たまたま属性を定義しているだけです。

要素定義のDTDバージョンでは、これらの興味深い (複雑になりうる) 型はすべてPCDATA と呼ばれ、その文字データの形式に関する詳細は指定できません (属性のCDATA の場合)。

スキーマは要素や属性の値の豊富な型を指定することによって、XMLインスタンスの構文記述からセマンティクス記述へと微妙に変化しています。こう書くと、構文解析の純粋主義者たちは「組み込みスキーマ型は構文として定義されるので、こうした型に基づくパターンもまた、構文形式である」と異議を唱えるかもしれません。しかし現実的に言って、ある要素がdate でなければならないと宣言するとき、要するに、その要素には日付が含まれなければならないと言っているわけです。もちろん、セマンティック情報を表現するのも悪くはありませんが、それは形式の宣言ではなく、アプリケーション・レベルに限定した方がいいのではないでしょうか。スキーマで規制しにくく、それでいてアプリケーションにとってスキーマの表す情報と同程度に重要なセマンティックが、(たとえ簡単なものでも) 結局は存在するのですから。たとえば、"stock-keeping unit" (在庫管理単位) は確かに "999-AA" のようになりますが、部品を出荷する際、13個を1ダース単位とする場合もあるのです。integer が13で割り切れることはXMLスキーマでは表現できません (したがって、widgetquantity (部品数) にこのレベルで制約を課すことはできません)。要するに、スキーマはDTDより機能が豊富であるとはいえ、XML文書が機能的に 妥当かどうか判断するために、依然として妥当性検査の事後処理をアプリケーション・レベルで行なう必要があります。

出現制約

XMLは強力な型宣言であると同時に、副要素の出現パターンの多重度 (カーディナリティー) を宣言するDTDの機能をも拡張しています。一方、DTDはすべての出現制約 (多重度) を常に1つずつ表現する点で、XMLスキーマよりも要領が悪いのです。

DTDでは、記号?*+ (それぞれ「ゼロまたは1つ」「ゼロまたは複数」「1つまたは複数」を意味する) のいずれかで多重度を指定します。つまり、疑問符で「1つ存在するか、またはまったく存在しない」ことを指定できるのを除き、DTD構文には、(1つの副タグか、入れ子になった一連の副タグかを問わず) 特定パターンが何回出現するかについての制限がないように見えます。したがって、上記のスキーマ例のように、prodName が1回から5回まで出現することを表現するのは困難なように見えます。同様に、XMLスキーマのminOccurs 属性がなければ、ある物が何回出現しなければならないかを表現できないように見えます (「少なくとも1回」というケースを除いて)。実際のところ、DTDの持つ最低限の機能でも、(洗練されてはいませんが) 十分です。以下の2つの制約は同等です。

リスト3: 「ドーナツが7個から12個まで」を表すXMLスキーマ構文
<xsd:element name="donutorder">
 <xsd:complexType>
 <xsd:sequence>
 <xsd:element name="donut" type="xsd:string"
 minOccurs="7" maxOccurs="12" />
 </xsd:sequence>
 </xsd:complexType>
</xsd:element>

<!ELEMENT donut (#PCDATA)>
<!ELEMENT donutorder
 (donut,donut,donut,donut,donut,donut,donut,
 donut?,donut?,donut?,donut?,donut?)>

もちろん、12ダースを1単位として注文するような場合には、気の遠くなるようなDTDになりますが。

列挙型

DTDとW3C XML Schemaのどちらも属性に列挙型を使用できますが、スキーマでは要素内容にも列挙型を使用できるという点で、より進んでいます。DTDが要素内容に列挙型を使用できないのは、純粋な欠点だと私は考えます。さらに、W3C XML Schemaが列挙型を扱う方法は一般的かつエレガントです。特化されたsimpleType には、列挙型facet を含めることができます。そのようなsimpleType は、自動的に、属性と要素のどちらのタイプの値にも適します。

このような構文の実例を見てみましょう。

リスト4: 列挙型属性を表すXMLスキーマ構文
<xsd:simpleType name="shoe_color">
 <xsd:restriction base="xsd:string">
 <xsd:enumeration value="red"/>
 <xsd:enumeration value="green"/>
 <xsd:enumeration value="blue"/>
 <xsd:enumeration value="yellow"/>
 </xsd:restriction>
</xsd:simpleType>
<xsd:element name="person" type="person_type">
 <xsd:attribute name="shoes" type="shoe_color"/>
</xsd:element>

<!ATTLIST person shoes (red | green | blue | yellow)>

DTDの属性宣言もこれと同様です (こちらの方が簡潔で良いかもしれません) が、shoe_color (靴の色) を要素内容の中に入れるモデルでは、DTDを使用するとうまくいきません。

リスト5: 列挙型要素を表すXMLスキーマ構文
<xsd:element name="shoes" type="shoe_color">

今後の方向

W3C XML Schemaを利用すれば、XMLプログラマーは、DTDでは不十分な文書制約上の新しい宣言を使用できます。多くのプログラマーにとって、XMLインスタンスの構文をスキーマで指定できることは、さまざまなXML作業分野の間で整合性を保つ優れた方法となります (もちろん、これに反論する人もいますが)。今後、スキーマがより身近になるにつれて、またスキーマを扱うツールの数が増えるにしたがって、確かにスキーマの重要度と有効範囲が広げられていくでしょう。

スキーマを初めて、しかも本格的に利用する1つの方法は、既存のDTDからXMLスキーマ形式への変換を自動化することです。もちろん、自動変換によって、XMLスキーマの新しい表現能力そのものを追加することはできません。しかし自動変換で良いテンプレートを作成し、それを基にして、希望に応じて特定の型制約を指定できるでしょう。DTDからスキーマへの自動変換ツールについては、参考文献の2つのリンクをご覧ください。


ダウンロード可能なリソース


関連トピック

  • W3C勧告候補 (2000年10月24日) はW3C XML Schemaの基本的な標準です。(訳注:W3C XML Schemaは、2001年5月3日にW3C勧告になりました。)
  • Extensible Markup Language (XML) 1.0 (第2版) - 2000年10月6日W3C勧告 は、w3.org/TR/REC-xml でご覧いただけます。「第2版は (1998年2月10日に初めて発表された) XMLの新しいバージョンではなく、第1版の正誤表に示された変更点を単に取り入れただけ」です。
  • 話が複雑になるかもしれませんが、XMLスキーマはW3CのXML Schemaだけではありません。RELAX (Regular Expression Language for XML) は現在、ISO/IEC DIS (Draft International Standard) 22250-1となっています。この標準は日本で最も普及していますが、特定の言語や文化に限定されてはいません。入門用として優れたサイトは、xml.gr.jp/relax/ です。
  • Yuichi Koike氏のDTDからXMLスキーマへの変換ツールをご覧ください(Perlが必要です)。
  • さまざまな情報に富む (少しとりとめのない ?) XMLに関する優れた紹介が、Inside XML (Steven Holzner著、New Riders発行、2001年、ISBN 0-7357-1020-1) にあります。的を突いたユーモアあふれる文を、この記事でも引用しました。
static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=XML
ArticleID=240796
ArticleTitle=XMLの論考: 第7回
publish-date=03012001