属性が存在するXMLスキーマ文書を作成
Meigara2.xmlでは属性が存在せず、MEIGARA要素の繰り返しという単純なものです。今からでも遅くない JAXPを学ぼう!(後編)XPathとXSLTを掘り下げるで紹介したshop.xmlには属性が存在します。しかし、これだけでは物足りないため、オプションの要素であるKOJI(麹)をABVとVOLUME要素の間に追加します。麹には白、黒、黄の3種類だけが存在するとします(正確には白と黄の組み合わせなどがあります)。従って、白、黒、黄以外はエラーとなるようにします。これらの条件を満たすXML文書をshop2.xmlとして作成したものがリスト6です。
001:<!--xml version="1.0" encoding="UTF-8"--> 002:<SHOP> 003: <GREETING OWNER="tomoharu">店主の好みの芋焼酎を厳選しました。</GREETING> 004: <MEIGARAS> 005: <MEIGARA> 006: <NAME KANA="がんこしょうちゅうや">がんこ焼酎屋</NAME><!-- 銘柄名 --> 007: <ABV UNIT="%">25</ABV><!-- alcohol by volume(アルコール度数)の略 --> 008: <KOJI>白</KOJI> 009: <VOLUME UNIT="ml">1800</VOLUME> 010: <PRICE UNIT="円">2630</PRICE> 011: <MANUFACTURER>大石酒造</MANUFACTURER> 012: </MEIGARA> 013: <MEIGARA> 014: <NAME KANA="きしんじゅ">貴心樹</NAME> 015: <ABV UNIT="%">25</ABV> 016: <KOJI>黒</KOJI> 017: <VOLUME UNIT="ml">1800</VOLUME> 018: <PRICE UNIT="円">1724</PRICE> 019: <MANUFACTURER>オガタマ酒造</MANUFACTURER> 020: </MEIGARA> 021: <MEIGARA> 022: <NAME KANA="とうじじゅんぺいべにいもげんしゅ">杜氏潤平紅芋原酒</NAME> 023: <ABV UNIT="%">38</ABV> 024: <VOLUME UNIT="ml">500</VOLUME> 025: <PRICE UNIT="円">2050</PRICE> 026: <MANUFACTURER>小玉醸造</MANUFACTURER> 027: </MEIGARA> 028: </MEIGARAS> 029:</SHOP>
shop2.xmlのXMLスキーマがリスト7のsample3.xsdです。
001:<?xml version="1.0" encoding="UTF-8"?> 002:<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 003: 004:<xsd:element name="SHOP" type="ShopType"/> 005: 006:<xsd:complexType name="ShopType"> 007: <xsd:sequence> 008: <xsd:element name="GREETING" type="GreetingType"/> 009: <xsd:element name="MEIGARAS" type="MeigarasType"/> 010: </xsd:sequence> 011:</xsd:complexType> 012: 013:<xsd:complexType name="GreetingType"> 014: <xsd:simpleContent> 015: <xsd:extension base="xsd:string"> 016: <xsd:attribute name="OWNER" type="xsd:string" use="required"/> 017: </xsd:extension> 018: </xsd:simpleContent> 019:</xsd:complexType> 020: 021:<xsd:complexType name="MeigarasType"> 022: <xsd:sequence> 023: <xsd:element name="MEIGARA" type="MeigaraType" minOccurs="0" maxOccurs="unbounded"/> 024: </xsd:sequence> 025:</xsd:complexType> 026: 027:<xsd:complexType name="MeigaraType"> 028: <xsd:sequence> 029: <xsd:element ref="NAME"/> 030: <xsd:element ref="ABV"/> 031: <xsd:element ref="KOJI" minOccurs="0" maxOccurs="1"/> 032: <xsd:element ref="VOLUME"/> 033: <xsd:element ref="PRICE"/> 034: <xsd:element ref="MANUFACTURER"/> 035: </xsd:sequence> 036:</xsd:complexType> 037: 038:<xsd:element name="NAME" type="NameType"/> 039:<xsd:element name="ABV" type="ABVType"/> 040:<xsd:element name="KOJI" type="KojiType"/> 041:<xsd:element name="VOLUME" type="VolumeType"/> 042:<xsd:element name="PRICE" type="PriceType"/> 043:<xsd:element name="MANUFACTURER" type="xsd:string"/> 044: 045:<xsd:complexType name="NameType"> 046: <xsd:simpleContent> 047 <xsd:extension base="xsd:string"> 048: <xsd:attribute name="KANA" type="xsd:string" use="required"/> 049: </xsd:extension> 050: </xsd:simpleContent> 051:</xsd:complexType> 052: 053:<xsd:complexType name="ABVType"> 054: <xsd:simpleContent> 055: <xsd:extension base="xsd:positiveInteger"> 056: <xsd:attribute name="UNIT" type="xsd:string" fixed="%"/> 057: </xsd:extension> 058: </xsd:simpleContent> 059:</xsd:complexType> 060: 061:<xsd:simpleType name="KojiType"> 062: <xsd:restriction base="xsd:string"> 063: <xsd:enumeration value="白"/> 064: <xsd:enumeration value="黒"/> 065: <xsd:enumeration value="黄"/> 066: </xsd:restriction> 067:</xsd:simpleType> 068: 069:<xsd:complexType name="VolumeType"> 070: <xsd:simpleContent> 071: <xsd:extension base="xsd:positiveInteger"> 072: <xsd:attribute name="UNIT" type="xsd:string" fixed="ml"/> 073: </xsd:extension> 074: </xsd:simpleContent> 075:</xsd:complexType> 076: 077:<xsd:complexType name="PriceType"> 078: <xsd:simpleContent> 079: <xsd:extension base="xsd:positiveInteger"> 080: <xsd:attribute name="UNIT" type="xsd:string" fixed="円"/> 081: </xsd:extension> 082: </xsd:simpleContent> 083:</xsd:complexType> 084: 085:</xsd:schema>
新しい概念
sample3.xsdでも新しい概念がたくさん登場しています。順を追って説明します。
属性を持った要素の定義
shop2.xmlの3行目のGREETING要素にはOWNER属性が存在します。このように属性が存在する要素のtype属性にビルトイン型を指定することはできません。新しい型を定義し、その中で属性を宣言します。13行目から19行目がその定義です。13行目のcomplexType要素のname属性には8行目で宣言したGREETING要素のtypeの値を指定しています。このことにより、宣言と定義を紐づけることが可能になります。15行目のxsd:extension要素のbase属性でその型の要素の型を指定します。16行目がOWNER属性の宣言です。use属性でrequiredを指定していますが、これは属性が必須であることを示しています。
ちなみにオプションの属性の場合、use属性はoptionalを指定します。optionalの場合でかつ属性を指定しない場合、default属性の値が指定されます。その他の属性定義で56行目、72行目、80行目は全て数値の単位をstring型の固定値で宣言しています。56行目はアルコール度数の「%」、72行目は容量の「ml(ミリリットル)」、80行目は価格の「円」を指定しています。
要素内容の制限
要素内容とは開始タグと終了タグの間にあるものを指します。61行目から67行目で要素内容を制限しています。KOJI要素は要素内容としてテキストのみであるため、先述の通り、61行目でsimpleType要素を使用しています。62行目でさらにrestriction要素を使用し、要素に指定できる範囲を限定しています。この場合、restriction要素の子要素にenumeration要素を列挙し、KojiTypeがこれらのうちのどれか1つのみ出現することを示しています。従って、XML文書のKOJI要素で青を指定したらエラーとなります。白、黒、黄のいずれかでなければなりません。
出現回数の制限
31行目のKOJI要素の参照でminOccurs="0" maxOccurs="1"
と指定しています。minOccursが最低の出現回数、maxOccursが最大の出現回数を指定します。この場合、minOccursが0、maxOccursが1であることから最低で0回、最大で1回と指定していることから、KOJI要素はオプションであることが分かります。shop2.xmlの3番目のMEIGARA要素にKOJI要素は存在しませんが、オプションであることからエラーにはなりません。お気づきかとは思いますが、その他の要素でminOccursとmaxOccursを指定していませんが、指定しない場合、minOccursが1、maxOccursも1とみなされます。つまり、必ず1回のみ出現することを示しています。
おさらい
W3C XML Schemaを系統立てて説明しようとするとそれだけで1冊の本になるので、そこまでの説明はしません。冒頭でも触れましたが、読み書きするうちに身に付くものであると考えています。今回学んだことは以下の通りです。
- 宣言と定義を分けることにより、複雑な構造のスキーマを記述することが可能となります。
- 要素には型が存在し、W3C XML Schemaに組み込まれたビルトイン型や、単純型(simpleType)、複合型(complexType)があります。
- 複合型は制限や拡張を使うことができます。今回は拡張の例だけ示しました。単純型の場合、制限、リスト、ユニオンが使用できます。今回は制限の例だけ示しました。
- 要素の出現回数を指定するにはminOccursとmaxOccursを使用できることを示しました。
サンプルコード
今回は特別にプロジェクトの作成は行っていません。前回作成したプロジェクトをそのまま使用できます。MyXMLValidatorのSOURCE_PATHにXML文書のパスを、XSD_PATHにXMLスキーマ文書のパスを指定し、ビルドし実行することで検証画面が表示されます。従って今回はサンプルコードとして、説明に使用したXML文書とXMLスキーマ文書を格納しています。ダウンロードしてご利用ください。
次回の後編は、少しだけ高度な話題を取り上げます。