W3C XML SchemaでXML文書の妥当性を検証する
スクラッチから構築するのも大変なので、今回は「今からでも遅くない JAXPを学ぼう!(前編) XPathとXSLTを体験する」を利用し、XML文書がXMLスキーマの妥当性検証で不合格になるようXML文書を修正して、チェックが行われていることを確認します。
「今からでも遅くない JAXPを学ぼう!(前編) XPathとXSLTを体験する」ではXMLスキーマを定義せず、与えられたXML文書が正しいものとして説明しましたが、今回はXMLスキーマを定義し、扱おうとしているXML文書が妥当か判定することから始めたいと考えています。実は、残念ですがGlassFish2.1はXSLT2.0に対応していません。XSLT2.0になってSchema Aware(「スキーマ対応(スキーマが認識できる)」とでも訳せばいいのでしょうか)のため、XSLTスタイルシートを使用する前にXMLスキーマで妥当性検証を行うことはできません。従って、ここではJAXPでの検証の仕方を説明します。
要するにXSLT1.0の場合、このようなプログラムを先に走らせることでXSLTスタイルシートを適用すべきか判断できるようになります。ここはあくまでW3C XML Schemaの説明のため、XSLTの使いやすさは度外視します。ちなみにXSLT2.0では<xsl:import-schema schema-location="sample1.xsd" />
のように指定することで、XMLスキーマによる妥当性検証が可能となります。
プロジェクトの作成
NetBeansで[ファイル]-[新規プロジェクト]を選択すると「新規プロジェクト」画面が表示されます。カテゴリの中なら「Java Web」を選択すると、プロジェクトに3つの選択肢が表示され、その中から「Web アプリケーション」を選択します。[次へ]ボタンをクリックすると「新規 Web アプリケーション」画面が表示されます。プロジェクト名は任意ですが、ここでは「XMLSchemaSample1」と入力します。[次へ]ボタンをクリックするとフレームワークを選択する画面が表示されますが、フレームワークは使用しないため[完了]ボタンをクリックしプロジェクトを作成します。NetBeansの左ペインのプロジェクトタブにXMLSchemaSample1が作成されているはずです。index.jspはこれから作成するXML文書の妥当性検証のためのMyXMLValidator.javaというServletへ遷移するためだけのJSPです。サンプルコードで確認してください。
Meigara2.xmlのXMLスキーマを定義する
リスト1は非常に簡単なXML文書です。MEIGARASという最上位要素にMEIGARA要素が0個以上無制限に指定可能です。MEIGARA要素の子要素としてNAME、ABV、VOLUME、PRICE要素があります。これらはすべてMEIGARA要素内で1回のみ指定可能で、必須とします。これをW3C XML Schemaで表したものが、リスト2のsample1.xsdです。
001:<?xml version="1.0" encoding="UTF-8"?> 002: 003:<MEIGARAS> 004: <MEIGARA> 005: <NAME>がんご焼酎屋</NAME> 006: <ABV>25</ABV><!-- alcohol by volume(アルコール度数)の略 --> 007: <VOLUME>1800</VOLUME> 008: <PRICE>2630</PRICE> 009: </MEIGARA> 010: <MEIGARA> 011: <NAME>一壺春</NAME> 012: <ABV>25</ABV> 013: <VOLUME>720</VOLUME> 014: <PRICE>1360</PRICE> 015: </MEIGARA> 016: <MEIGARA> 017: <NAME>杜氏潤平紅芋原酒</NAME> 018: <ABV>38</ABV> 019: <VOLUME>500</VOLUME> 020: <PRICE>2050</PRICE> 021: </MEIGARA> 022:</MEIGARAS>
001:<?xml version="1.0" encoding="UTF-8"?> 002:<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 003: targetNamespace="http://kawakubo.jp/sample1"> 004: 005:<xs:element name="MEIGARAS"> 006: <xs:complexType> 007: <xs:sequence minOccurs="0" maxOccurs="unbounded"> 008: <xs:element name="MEIGARA"> 009: <xs:complexType> 010: <xs:sequence> 011: <xs:element name="NAME" type="xs:string"/> 012: <xs:element name="ABV" type="xs:int"/> 013: <xs:element name="VOLUME" type="xs:int"/> 014: <xs:element name="PRICE" type="xs:int"/> 015: </xs:sequence> 016: </xs:complexType> 017: </xs:element> 018: </xs:sequence> 019: </xs:complexType> 020:</xs:element> 021: 022:</xs:schema>
「MEIGARASという最上位要素にMEIGARA要素が0個以上無制限に指定可能」が7行目のminOccurs="0" maxOccurs="unbounded">
です。NAME、ABV、VOLUME、PRICEは「MEIGARA要素内で1回のみ指定可能で、必須」と説明しましたが、11~14行目でminOccursやmaxOccursを指定していません。これらの指定を省略した場合、それぞれ1を指定することとなり、条件を満たすことになります。それぞれの要素でxs:stringやxs:intを指定し、データ型の指定が可能です。詳しくは後編で説明します。