新たな概念
新たな概念として紹介するまでもありませんが、documentation要素は適切に使用するとXMLスキーマ文書自体や要素の説明などが可能となります。コメントと大きく違うのが要素として記述できるため、XSLTを使ってHTMLに変換する場合など、説明を有効に利用できます。
xml:lang属性
6行目のxml:lang属性において2つの点で変だと思われた方もいるのではないでしょうか。まずはxmlという名前空間宣言が存在しないにもかかわらず、xmlという接頭辞を使用していることです。実はxml自体が予約語となっており、XMLスキーマの作成者が勝手に新たな要素や属性を作ることはできません。名前空間自体は「http://www.w3.org/XML/1998/namespace」なのですが、宣言しなくてもエラーにはならないようになっています。
2つ目は、属性に接頭辞が付くということです。このように接頭辞が付く属性をグローバル属性といいます。xml:lang、xml:space、xml:base属性は名前空間なしに要素に縛られずに使える属性です。このように要素に結び付かない属性のことをグローバル属性と呼びます。今回は説明しませんが、グローバル属性はこの3つだけでなく、誰でも作成できます。ただし、使用する場合は、要素の場合と同じく名前空間宣言が必要となります。
ちなみにxml:lang属性とはその属性、もしくはその子要素以下の要素内容の自然言語に何を使用しているかを指定するものです。6行目のようにjpと指定すれば日本語であることを、enであれば英語であることを指定します。したがって、最上位要素でxml:lang="ja"と指定すると、その文書の要素内容の自然言語は日本語となります。
グループとして要素の塊を定義できる
4行目から21行目がグループを定義している箇所です。芋焼酎とトスカーナワインで共通な要素NAME、ABV、VINTAGE、VOLUME、PRICE、MANUFACTURERをsequenceでまとめています。ShochuTypeの48行目とWineTypeの55行目でこのグループ(meigaraGroup)を参照しています。ShochuTypeに特有なKOJI要素を49行目、WineTypeに特有なRANK要素を56行目で参照することで、共通な要素を2度宣言することを避けることができます。日本酒やウィスキーなども容易に追加できることが分かると思います。8行目にも記述していますが、このような再利用を行うのにsubstitutionGroupを使用することもできます。
要素の選択的な出現
sequenceが要素の並びを指定するのに対し、40行目から43行目のchoiceはSHOCHU要素かWINE要素のどちらかが出現することを定義しています。choice要素に出現回数を0回以上と指定しているため、実際にはSHOCHU要素とWINE要素が順番に関係なく何回でも出現可能であることを指定しています。
XML文書とXMLスキーマ文書を関連付ける
中編の冒頭でTomcatのweb.xmlとそのXMLスキーマ文書であるweb-app_2_4.xsdの冒頭を紹介しました。実はweb.xmlの最上位要素であるweb-app要素とweb-app_2_4.xsdの最上位要素であるschema要素に両者を結び付ける記述があります。
まずはweb.xmlから
001:<web-app xmlns="http://java.sun.com/xml/ns/j2ee" 002: xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 003: xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" 004: version="2.4">
ポイントとなるのは3行目です。xsi:schemaLocationに名前空間とXMLスキーマのURIを指定することでweb.xmlのXMLスキーマがweb-app_2_4.xsdということがわかります。その属性値は空白文字(この場合半角空白)で区切られています。空白文字の左側がXMLスキーマの名前空間、右側がXMLスキーマのURIになります。先述のshop3.xmlをリスト4のshop4.xmlのようにXMLスキーマ文書を指すように書き換えます。
001:<?xml version="1.0" encoding="UTF-8"?> 002:<sp:SHOP 003: xsi:schemaLocation="http://europa.kawakubo.jp/XMLSchemaSample1 sample5.xsd" 004: xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 005: xmlns:sp="http://europa.kawakubo.jp/XMLSchemaSample1"> 006: <sp:GREETING OWNER="tomoharu">店主の好みの芋焼酎を厳選しました。</sp:GREETING> 007: <sp:MEIGARAS> 008: <sp:SHOCHU> 009: <sp:NAME KANA="ガンコショウチュウヤ">がんこ焼酎屋</sp:NAME> 010: <sp:ABV UNIT="%">25</sp:ABV><!-- alcohol by volume(アルコール度数)の略 --> 011: <sp:VOLUME UNIT="ml">1800</sp:VOLUME> 012: <sp:PRICE UNIT="円">2630</sp:PRICE> 013: <sp:MANUFACTURER>大石酒造</sp:MANUFACTURER> 014: <sp:KOJI>白</sp:KOJI> 015: </sp:SHOCHU> 016: <sp:WINE> 017: <sp:NAME KANA="ブルネッロ・ディ・モルタルチーノ">Brunello di Montalcino</sp:NAME> 018: <sp:VINTAGE>2004</sp:VINTAGE> 019: <sp:PRICE UNIT="円">10000</sp:PRICE> 020: <sp:RANK>DOCG</sp:RANK> 021: </sp:WINE>
shop4.xmlのXMLスキーマ文書がリスト5のsample5.xsdです。
001:<?xml version="1.0" encoding="UTF-8"?> 002:<xsd:schema 003: targetNamespace="http://europa.kawakubo.jp/XMLSchemaSample1" 004: xmlns:xsd="http://www.w3.org/2001/XMLSchema" 005: xmlns:sp="http://europa.kawakubo.jp/XMLSchemaSample1" 006: elementFormDefault="qualified"> 007: 008:<xsd:group name="meigaraGroup"> 009: <xsd:annotation> 010: <xsd:documentation xml:lang="jp"> 011: このグループは芋焼酎とトスカーナワインに共通した 012: 要素を集めたもの。置換グループ(substitutionGroup) 013: を使っても要素の塊を再利用することができる。 014: </xsd:documentation> 015: </xsd:annotation> 016: <xsd:sequence> 017: <xsd:element ref="sp:NAME"/> 018: <xsd:element ref="sp:ABV" minOccurs="0" maxOccurs="1"/> 019: <xsd:element ref="sp:VINTAGE" minOccurs="0" maxOccurs="1"/> 020: <xsd:element ref="sp:VOLUME" minOccurs="0" maxOccurs="1"/> 021: <xsd:element ref="sp:PRICE"/> 022: <xsd:element ref="sp:MANUFACTURER" minOccurs="0" maxOccurs="1"/> 023: </xsd:sequence> 024:</xsd:group> 025: 026:<xsd:element name="SHOP" type="sp:ShopType"/> 027: 028:<xsd:complexType name="ShopType"> 029: <xsd:sequence> 030: <xsd:element name="GREETING" type="sp:GreetingType"/> 031: <xsd:element name="MEIGARAS" type="sp:MeigarasType"/> 032: </xsd:sequence> 033:</xsd:complexType> 034: 035:<xsd:complexType name="GreetingType"> 036: <xsd:simpleContent> 037: <xsd:extension base="xsd:string"> 038: <xsd:attribute name="OWNER" type="xsd:string" use="required"/> 039: </xsd:extension> 040: </xsd:simpleContent> 041:</xsd:complexType> 042: 043:<xsd:complexType name="MeigarasType"> 044: <xsd:choice minOccurs="0" maxOccurs="unbounded"> 045: <xsd:element name="SHOCHU" type="sp:ShochuType"/> 046: <xsd:element name="WINE" type="sp:WineType"/> 047: </xsd:choice> 048:</xsd:complexType>
3行目のtargetNamespaceの値こそ、このXMLスキーマの名前空間となります。4行目で3行目で使用したxsiという接頭辞の名前空間宣言をしています。6行目がよく忘れる属性です。忘れると値がunqualifiedとデフォルトが指定されます。要するに要素に接頭辞を付けるか付けないかの指定を行います。筆者も久しぶりにXMLスキーマを記述し、この指定を忘れていたため、しばらく悩む羽目になりました。MyXMLValidatorの結果は図1のようになります。
接頭辞が必要ない場合
shop3.xmlのように接頭辞を必要としない場合のXMLスキーマの関連付けを説明します。これは至って簡単です。schemaLocation属性をnoNamespaceSchemaLocationに変え、名前空間宣言を削除するだけです。リスト6がその宣言をしているshop5.xmlです。
001: 002:<SHOP 003: xsi:noNamespaceSchemaLocation="sample5.xsd" 004: xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 005: <GREETING OWNER="tomoharu">店主の好みの芋焼酎を厳選しました。</GREETING>
XMLスキーマはsample4.xsdがそのまま使えます。ただし、業務に耐えうるXMLスキーマを作成する場合、接頭辞を付ける方が再利用性という点から優れています。schemaLocation属性で名前空間宣言をして、接頭辞を付けることをおすすめします。