XML Schemaで文字列パターンを定義するXMLテクニック集(9)(2/3 ページ)

» 2004年01月14日 10時00分 公開
[山田祥寛@IT]

XML Schemaで要素モデルを定義する

アイコン

共通する子要素を持つ要素モデルを複数個所に記述する場合には、要素モデルを別の場所で定義しておき、それを参照できると便利です。<xsd:group>要素を使えば要素モデルの定義と参照が可能になります。

カテゴリ XML Schema
関連要素 <xsd:group>
関連記事 XML Schemaで属性グループを定義する

 同じような内容のコードを繰り返し書くのは無駄な作業であるばかりでなく、コードの保守性も著しく低下させるものです。例えば、以下のようなケースを想定してみましょう。

 書籍情報を表す<book>要素と、記事情報を表す<article>要素は、いずれも以下のような共通の子要素(要素モデル)を持つものとします。

要素名 概要
<name> 書籍・記事名
<author> 著者名
<published> 出版社
<pdate> 公開日
表 <book>/<article>共通の要素

 ただし、<book>要素配下には書籍の価格を表す<price>要素が、<article>要素配下には連載(シリーズ名)を表す<series>要素が、それぞれ独自に必要であるかもしれません。

 このようなケースにおいては、もちろん、<book>、<article>要素それぞれについて、<xsd:complexType>要素を用いてすべての子要素の構造を定義しても構いません(その方法については、別稿「XML Schemaで複雑型要素を定義する」で紹介しています)。しかし、後々に共通の子要素を拡張・変更したいといった場合、双方をいちいち修正しなければならないのは間違いのもとです。そもそもこの例の場合には、2つだけですからまだしも、実際のXML文書では共通の要素モデルを複数個所で使用することもあれば、共通の要素モデル自体が極めて複雑多岐にわたっているケースも少なくありません。

 そのような場合に備えて、共通の要素モデルについては、<xsd:group>要素で要素モデルのグループをあらかじめ作成しておき、必要な個所から参照させる方法を採用するのがより適切です。これによって、将来のスキーマ変更時にも簡単に対応でき、修正漏れや間違いなどの恐れも少なくなります。

 以下に、具体的な例を見てみましょう。なお、対象となるXML文書については、別稿「XML Schemaで文字列パターンを定義する」で用いたbooks.xmlを使用することにします。

books_elements.xsd

<?xml version="1.0" encoding="Shift_JIS" ?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <xsd:element name="books">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element name="book" type="book_type"
          minOccurs="0" maxOccurs="unbounded" />
      </xsd:sequence>
      <xsd:attribute
          name="name" type="xsd:string" use="required" />
    </xsd:complexType>
  </xsd:element>
  <xsd:group name="bookBasicInfo">
    <xsd:sequence>
      <xsd:element name="title" type="xsd:string" />
      <xsd:element name="author" type="xsd:string" />
      <xsd:element name="published" type="xsd:string" />
      <xsd:element name="price" type="xsd:positiveInteger" />
      <xsd:element name="publishDate" type="xsd:date" />
    </xsd:sequence>
  </xsd:group>

  <xsd:complexType name="book_type">
    <xsd:sequence>
      <xsd:group ref="bookBasicInfo" />
      <xsd:element name="category" type="xsd:string" />
      <xsd:element name="keywords" type="xsd:string" />
    </xsd:sequence>
    <xsd:attribute name="isbn" type="xsd:string" use="required" />
  </xsd:complexType>
</xsd:schema>


 <xsd:group>要素は、要素モデル(グループ)を定義する場合と、定義された要素モデルを参照する場合の、双方のケースで使用することができます。

(1)要素モデルを定義する

 要素モデルを定義する場合の基本的な構文は、以下のとおりです。

<xsd:group name="要素モデル名">
  要素モデルの定義
</xsd:group>

 要素モデルを定義する場合には、<xsd:sequence>、<xsd:all>、<xsd:any>のいずれかの要素を子要素として採用できます。<xsd:sequence>要素の役割については、別稿「XML Schemaで複雑型要素を定義する」を参照してください。<xsd:all>要素と<xsd:any>要素については、あらためて別稿で紹介します。

(2)定義済みの要素モデルを参照する

 定義済みの要素モデルを参照するには、<xsd:sequence>や<xsd:complexType>要素などの配下に以下のように記述します。

<xsd:group ref="要素モデル名" />


 ref属性には(1)で定義したname属性に対応する要素グループ名を指定する必要があります。また、参照時にはmaxOccurs、minOccurs属性を併せて指定することで、要素モデルの内容が登場する回数を厳密に指定することも可能です。これら属性値に関する詳細は、別稿「XML Schemaで複雑型要素を定義する」を参照してください。

 なお、maxOccurs、minOccurs属性はref属性とのセットでなければ指定できません(name属性と同時には使用できません)し、name属性とref属性とを同時に使用することはできませんので、注意してください。


 この操作によって、上のサンプルでは、<xsd:group name="…">で指定された要素モデル「bookBasicInfo」が<book>要素(複雑型“book_type”)に追加されました。要素モデルに対して、さらに要素ノードを拡張したいという場合には、<xsd:group ref="…" />に続けて<xsd:element>要素などを記述できます。上記の例は、以下のコードと同意ですので、比較してみるとより分かりやすいでしょう。

<xsd:complexType name="book_type">
  <xsd:sequence>
    <xsd:element name="title" type="xsd:string" />
    <xsd:element name="author" type="xsd:string" />
    <xsd:element name="published" type="xsd:string" />
    <xsd:element name="price" type="xsd:positiveInteger" />
    <xsd:element name="publishDate" type="xsd:date" />
    <xsd:element name="category" type="xsd:string" />
    <xsd:element name="keywords" type="xsd:string" />
  </xsd:sequence>
  <xsd:attribute name="isbn" type="xsd:string" use="required" />
</xsd:complexType>


 <xsd:group name="…">で定義された要素モデルがあたかも変数のように<xsd:group ref="…" />によって引用されていたことが分かるはずです。

 実際に、妥当性検証を行いたい場合には、別稿「XML SchemaでXML文書の妥当性を検証する」のサンプルを参考にしてください。変更個所は、XMLSchemaCache.addメソッドの第2引数(XML Schemaのファイル名)のみです。スキーマ文書を書いてみるだけでは、スキーマ文書そのものの妥当性を判断できませんが、パーサの処理を介することでスキーマの正否を確認できます。

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。