連載
» 2004年05月26日 10時00分 公開

XMLテクニック集(13):XML Schemaで空要素を定義する (2/3)

[山田祥寛,@IT]

XML Schemaでnull値の許容を定義する

アイコン

要素の値を取りあえずブランクにしておきたいケースでは、対象の要素定義に「nillable="true"」を記述し、XML文書側で「xsi:nil="true"」と明示的に宣言します。これでパーサの検証時にnull値が許容されます。

カテゴリ XML Schema
関連要素 <xsd:element>
関連記事 XML Schemaで空要素を定義する
XML Schemaで複数の型を結合する

 別稿「XML Schemaで空要素を定義する」では、空要素を規定するための方法について紹介しました。しかし、これはあらかじめ要素が空であることが「決まっている」場合の手法です。例えば、書籍情報などでまだ発刊日が決まっていない、価格が決まっていないなどの理由で、取りあえずデータをブランクのままにしておきたいケースもあります。

 文字列データの場合、空文字列をセットしてもパーサの検証に引っ掛かることはありませんが、数値や日付データの場合、ブランクは妥当性エラーです。このような場合には、どのようにしたらよいのでしょう。

 以下では、暫定的なnullデータに対処する2つの方法を紹介します。対象となるXML文書は、別稿「XML Schemaで文字列パターンを定義する」で用いたbooks.xmlを参照してください。

books_nullable_pre.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:simpleType name="nullable">
    <xsd:restriction base="xsd:string">
      <xsd:enumeration value="" />
    </xsd:restriction>
  </xsd:simpleType>
  <xsd:simpleType name="price_int">
    <xsd:restriction base="xsd:positiveInteger">
      <xsd:maxInclusive value="10000" />
      <xsd:minInclusive value="1000" />
    </xsd:restriction>
  </xsd:simpleType>

  <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">
        <xsd:simpleType>
          <xsd:union>
            <xsd:simpleType>
              <xsd:restriction base="nullable" />
            </xsd:simpleType>
            <xsd:simpleType>
              <xsd:restriction base="price_int" />
            </xsd:simpleType>
          </xsd:union>
        </xsd:simpleType>
      </xsd:element>

      <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:schema>


 まず1つ目の例は、別稿「XML Schemaで複数の型を結合する」で紹介した、<xsd:union>要素を用いる手法です。要素に対して、列挙値として空文字列を含むデータ型と本来規定すべきデータ型とを結合したうえで定義します。

 ただし、この手法は記述が冗長であるうえ、常に空文字列を許す定義となってしまい、厳密に制約するという観点からはあまり好ましくありません。

 そこで登場するのが、以下の手法です。

books_nullable.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: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"
                   nillable="true"/>
      <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:schema>


 対象の要素定義に「nillable="true"」という一文を追記しています。これによって、<price>要素に対してnull値が許されるようになりました。ただし、無条件にnullを許すというわけではありません。

 元となるbooks.xmlを見てみましょう。

[books.xml]

<?xml version="1.0" encoding="Shift_JIS" ?>
<atit:books xmlns:atit="urn:bookList" name="書籍情報一覧"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <book isbn="ISBN4-7981-0189-3">
    <title>10日でおぼえるJSP/サーブレット入門教室</title>
    <author>Y.Yamada</author>
    <published>翔泳社</published>
    <price xsi:nil="true"></price>
    <publishDate>2002-05-17</publishDate>
    <category>JSP&サーブレット</category>
    <keywords>JSP サーブレット Tomcat J2SE</keywords>
  </book>
</atit:books>


 <price>要素に「xsi:nil="true"」と明示的に宣言した場合にのみ<price>要素にnull値のセットを許すのです。xsi:nil属性が指定されていない場合、<price>要素にnullを指定することは許されません。なお、xsi:nil属性を使用する場合には、必ずxsi名前空間の宣言を行うのを忘れないようにしてください。

 これによって、より明示的なnullデータの管理を行うことができるというわけです。

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


Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

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

メールマガジン登録

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