本文へジャンプ

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む


お客様が developerWorks に初めてサインインすると、プロフィールが作成されます。プロフィールで選択した情報は公開されますが、いつでもその情報を編集できます。お客様の姓名(非表示設定にしていない限り)とディスプレイ・ネームは、投稿するコンテンツと一緒に表示されます。

送信されたすべての情報は安全です。

  • 閉じる [x]

developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む


送信されたすべての情報は安全です。

  • 閉じる [x]

ヒント: パーサにどこでスキーマを探せばよいかを教える

JAXP 1.2でさらに便利になった文書の妥当性検証

Benoit Marchal (bmarchal@pineapplesoft.com), Consultant, Pineapplesoft
Benoit Marchal氏は、ベルギーのナミュールを拠点にしたコンサルタントおよび著述家です。彼の著作には、 XML by Example(Que社、邦訳: インプレス社「実例で学ぶXML」。間もなく第2版が出版される予定です)、 Applied XML Solutions および XML and the Enterprise があります。また、Gamelanのコラムや、developerWorks XML zoneのコラムWorking XML の著者でもあります。最新プロジェクトの詳細については、www.marchal.com をご覧ください。

概要: このヒントでは、XMLスキーマとJAXP 1.2を利用して、より堅牢な文書の妥当性検証を実装する方法を紹介します。SAXパーサとDOMパーサ向けの例が掲載されています。

日付:  2003年 5月 22日
レベル:  初級 この記事の原文:  英語
アクティビティー: 2926 ビュー
お気軽にご意見・ご感想をお寄せください: 


スキーマについての論議のほとんどは、利用できる最良のボキャブラリや、スキーマを効率よく組織する方法 (Russian Doll (ロシア人形)、Venetian Blind (ベネチアン・ブラインド)、Salami Slice (サラミ・スライス) など) を中心としています。さらに、最適なスキーマ言語についての論議 -- DTD、W3CのXMLSchema、OASISのRelax NGのどれが最適なのか? -- も進行中です。

こうしたことは重要な考慮事項です。しかし、あなたがXMLアプリケーションを設計するときには、スキーマで何をするかということの方がさらに重要です。このヒントでは、Java API for XML Processing (JAXP) 1.2の新機能について考察しますが、これをお読みになれば、文書がスキーマに合致しているかどうか妥当性を検証する時に、より柔軟に対応できます。

文書の妥当性検証

一般に、アプリケーションは、エラー処理の一環として、XML文書が既知のスキーマのリストに合致しているかどうか妥当性を検証します。スキーマは、要素の名前、属性、そしてそのデータ・タイプ (integer、string、dateなど) といったボキャブラリを記述するものです。文書がスキーマに合致していると妥当性が検証される場合、アプリケーションで認識されるボキャブラリに従うことになります。結局、検証することは有用なのですが、もしアプリケーションが要素を認識しない場合には、文書を処理する上で何が大切なのでしょうか?

まだ有用なものではないのですが、既知のスキーマにアプリケーションが合致しているかどうか妥当性の検証を行うことが重要です。ただ、この検証は、JAXP 1.2が登場するまでは「言うは易し行うは難し」という代物でした。たとえば、文書を手軽にスキーマと関連付けるときにはどうしますか。ほとんどの場合、 xsi:schemaLocation 属性を使うことになります。この属性は、名前空間URIと関連付けられたスキーマ・ファイルと組み合わせて使用します (名前空間のない文書では、 xsi:noNamespaceSchemaLocation 属性を使用します)。リスト1では、 schemaLocation 属性が、 http://ananas.org/2003/tips/validate 名前空間を、ファイル simple.xsd に関連付けています。


リスト1. xsi:schemaLocation属性を使うXML文書
                
<?xml version="1.0"?>
<simple:Root
   xmlns:simple="http://ananas.org/2003/tips/validate"
  
   xsi:schemaLocation="http://ananas.org/2003/tips/validate simple.xsd">
      Document content comes here.
</simple:Root>
			

この属性は、XMLスキーマを管理するための簡単な解決策になりますが、重大な欠陥が1つあります。つまり、ご使用のアプリケーションが xsi:schemaLocation 属性を制御できると見なされてしまうのです。アプリケーションによっては、これが当てはまる場合もありますし、当てはまらない場合もあります。以下のシナリオを考えてみてください。

  • Corel XMetaLやXMLmind XML EditorなどのXMLエディターによって、適切なファイルを指すよう xsi:schemaLocation 属性を変更することが可能である。
  • XMやCocoonのようなWeb公開フレームワーク側では、作成者が xsi:schemaLocation を正確に設定しているものと想定するが、複数の作成者がサイトに関わった場合には正確に設定されていないものが存在する場合がある。
  • 着信XML文書を扱う電子商取引サーバーはそれらの文書の妥当性を検証する必要があるが、他のパーティーがスキーマを正しく設定したということを信頼できない場合がある。

このようなシナリオに示されているように、 xsi:schemaLocation 属性は、小規模なアプリケーションでは十分に有用ですが、分散が進むと管理が著しく難しくなります。とりわけ、スキーマが別のコンピュータでも同じ名前で保管されるといった可能性は低いものです。

当然、文書が正しくないという危険性が存在する場合に、アプリケーションはその妥当性を検証します。そのような文書が、 xsi:schemaLocation などの内容によって変わるのであれば、妥当性の検証を堅牢にすることはできません。いったい、文書の残りの部分よりも属性のほうが正しいということがあり得るでしょうか。明らかに、別の解決策、すなわち、より一層の制御権をアプリケーションに委ねる方策が必要です。


JAXP 1.2でのスキーマ・サポート

URIとプロパティ

JAXPでは、URIをプロパティと属性の識別子として使用します。このことは、URIを名前空間識別子として使用することと矛盾しません。しかし、残念ながら、URIのこのような使用方法が少し混乱を招くことがあります。ユーザーは、 http:// で始まるものはすべてWebサイトだと思い込んでいます。でもこの場合はWebサイトではありません。それらのURIは識別子ですので、ブラウザーでアクセスしようとしても、ほとんどの場合、"404 - File not found" のエラー・メッセージに迎えられることになります。

スキーマ仕様では、 xsi:schemaLocation に起因する堅牢性の不足が正しく認識されています。仕様によると、パーサにとっては xsi:schemaLocation はヒントに過ぎないもので、パーサは他の方法を使用して適用するスキーマを決定できます。残念ながら、仕様では他の方法については教えてくれません。JAXPのメンテナンス・リリースであるJAXP 1.2がこの穴を埋めてくれます。これには、Javaプラットフォームでの標準メカニズムが備えられています。

基本的に、JAXP 1.2は2つの新しいプロパティ (SAXパーサ用) と、スキーマの妥当性検証を制御する2つの新しい属性 (DOMパーサ用) を定義します。最初のプロパティー ( http://java.sun.com/xml/jaxp/properties/schemaLanguage ) は、使用するスキーマ言語を指定します。今のところ、受け入れられる値は http://www.w3.org/2001/XMLSchema (XMLスキーマに関するW3C勧告)だけです。将来のリリースでは、Relax NGや他のスキーマ言語向けに、別の値がサポートされる予定です。

2番目のプロパティ ( http://java.sun.com/xml/jaxp/properties/schemaSource ) は、スキーマの場所を設定します。これは非常に興味深い点の1つです。以下のような、さまざまな値を使用できます。

  • スキーマのURIを含む文字列。
  • スキーマの内容を含む InputStream オブジェクト。
  • スキーマを指す InputSource オブジェクト。
  • スキーマ・ファイルを指す File オブジェクト。
  • このような定義済みタイプのいずれかを含む配列。この配列は、異なるスキーマに適合できる文書をアプリケーションが受け入れる場合に役立ちます。

SAXの例

リスト2 には、JAXP 1.2で新しいプロパティを使用して、SAXパーサで文書の妥当性を検証する方法が示されています。文書の妥当性を検証するためにSAXパーサを使用するときには、以下のようにします。

  1. SAXParserFactory オブジェクトを作成します。
  2. 名前空間認識プロパティと妥当性検証プロパティをtrueに設定します。
  3. SAXParser オブジェクトを取得します。
  4. スキーマ言語とスキーマ・ソースのプロパティを設定します (これは、JAXP 1.2とスキーマで新しく導入された部分です)。
  5. 文書を構文解析します。パーサには、 ErrorHandler オブジェクトへのアクセス権が必要です。

リスト2. JAXP 1.2の説明
                
package org.ananas.tips;
import java.io.*;
import org.xml.sax.*;
import javax.xml.parsers.*;
public class ValidateSAX
{
   public static String SCHEMA_LANGUAGE =
      "http://java.sun.com/xml/jaxp/properties/schemaLanguage",
                        XML_SCHEMA =
      "http://www.w3.org/2001/XMLSchema",
                        SCHEMA_SOURCE =
      "http://java.sun.com/xml/jaxp/properties/schemaSource";
   public final static void main(String[] args)
      throws IOException, SAXException, ParserConfigurationException
   {
      if(args.length < 2)
      {
         System.err.println("usage is:");
         System.err.println(" java -jar tips.jar -validatesax "
                            + "input.xml schema.xsd");
         return;
      }
      File input = new File(args[0]),
           schema = new File(args[1]);
      SAXParserFactory factory = SAXParserFactory.newInstance();
      factory.setNamespaceAware(true);
      factory.setValidating(true);
      SAXParser parser = factory.newSAXParser();
      try
      {
         parser.setProperty(SCHEMA_LANGUAGE,XML_SCHEMA);
         parser.setProperty(SCHEMA_SOURCE,schema);
      }
      catch(SAXNotRecognizedException x)
      {
         System.err.println("Your SAX parser is not JAXP 1.2 compliant.");
      }
      parser.parse(input,new ErrorPrinter());
   }
}
			

ErrorHandlerと妥当性の検証


妥当性の検証プロパティは、検証エラーを ErrorHandler オブジェクトにレポートするようパーサに命令します。これは実際には、 ErrorHandler を登録しないと、エラー・メッセージが分からないということです。プログラマーの中には、パーサが文書の妥当性を検証できない場合には、パーサが例外をスローすることを望む方もいますが、これは、SAXパーサの動作ではありません。

リスト2 をテストするには、JAXP 1.2準拠パーサが必要です。お気に入りのパーサの資料を調べるか、最新バージョンのApache Xercesをダウンロードしてください (私は、このヒントを準備するにあたってバージョン2.4.0を使用しました)。パーサがJAXP 1.2準拠ではない場合、プロパティを設定しようとすると、 SAXNotRecognizedException 例外がスローされます。これは、最新バージョンのXercesにアップグレードしなさいという合図です。

リスト2 の場合は、リスト3に示されているように、コンソールに妥当性の検証エラーを表示する DefaultHandler オブジェクトを登録するだけです。あなたのアプリケーションでは、文書の内容に何らかの処理を行うような、さらに面白いハンドラーを登録できます。


リスト3. ErrorPrinter.java
                
package org.ananas.tips;
import java.text.*;
import org.xml.sax.*;
import org.xml.sax.helpers.*;
public class ErrorPrinter
   extends DefaultHandler
{
   private MessageFormat message =
      new MessageFormat("({0}: {1}, {2}): {3}");
   private void print(SAXParseException x)
   {
      String msg = message.format(new Object[]
                                  {
                                     x.getSystemId(),
                                     new Integer(x.getLineNumber()),
                                     new Integer(x.getColumnNumber()),
                                     x.getMessage()
                                  });
      System.out.println(msg);
   }
   public void warning(SAXParseException x)
   {
      print(x);
   }
   public void error(SAXParseException x)
   {
      print(x);
   }
   public void fatalError(SAXParseException x)
      throws SAXParseException
   {
      print(x);
      throw x;
   }
}


DOMはどうなるの?

JAXP 1.2では、 リスト4 に示されているように、DOMパーサのスキーマ・サポートも定義されています。その手順はSAXパーサの手順と非常に似ていて、相違点は、パーサ・オブジェクトにプロパティを設定する代わりに、ファクトリ・オブジェクトに属性を設定することだけです。詳しい手順は、以下のとおりです。

  1. DOMBuilderFactory オブジェクトを作成します。
  2. 名前空間認識プロパティ妥当性検証プロパティを true に設定します。
  3. スキーマ言語とスキーマ・ソースの属性を設定します。パーサがJAXP 1.2準拠ではない場合、 IllegalArgumentException 例外がスローされます。
  4. DocumentBuilder オブジェクト (パーサ) を取得します。
  5. ErrorHandler オブジェクトをパーサに登録します。
  6. 文書を構文解析します。

この例は、検査を行うだけのものです。あなたのアプリケーションでは、解析ツリーを使用してさらに面白いことができます。


リスト4. ValidateDOM.java
                
package org.ananas.tips;
import java.io.*;
import org.xml.sax.*;
import javax.xml.parsers.*;
public class ValidateDOM
{
   public static String SCHEMA_LANGUAGE =
      "http://java.sun.com/xml/jaxp/properties/schemaLanguage",
                        XML_SCHEMA =
      "http://www.w3.org/2001/XMLSchema",
                        SCHEMA_SOURCE =
      "http://java.sun.com/xml/jaxp/properties/schemaSource";
   public final static void main(String[] args)
      throws IOException, SAXException, ParserConfigurationException
   {
      if(args.length < 2)
      {
         System.err.println("usage is:");
         System.err.println(" java -jar tips.jar -validatedom "
                            + "input.xml schema.xsd");
         return;
      }
      File input = new File(args[0]),
           schema = new File(args[1]);
      DocumentBuilderFactory factory =
         DocumentBuilderFactory.newInstance();
      factory.setNamespaceAware(true);
      factory.setValidating(true);
      try
      {
         factory.setAttribute(SCHEMA_LANGUAGE,XML_SCHEMA);
         factory.setAttribute(SCHEMA_SOURCE,schema);
      }
      catch(IllegalArgumentException x)
      {
         System.err.println("Your DOM parser is not JAXP 1.2 compliant.");
      }
      DocumentBuilder parser = factory.newDocumentBuilder();
      parser.setErrorHandler(new ErrorPrinter());
      parser.parse(input);
   }
}


さらに堅牢なXMLアプリケーションに向けて

XMLスキーマを利用して、堅牢な妥当性の検証を実装する際には、あなたのアプリケーションが文書妥当性を検証するときに、(当然のことですが) それらの文書が正しいという思い込みを持ってはならないことを念頭においてください。さらに言うならば、文書が適切な xsi:schemaLocation 属性を持っていると思い込まないようにしてください。


参考文献

  • この記事で使用された ソース・コード をダウンロードしてください。さらに、最新バージョンの Apache Xerces か、別のJAXP 1.2準拠のパーサも必要です。

  • XMLmind XML Editor Corel XMetaL は、スキーマをサポートする代表的なXMLエディターです。 XMCocoon は、代表的な公開ソリューションです。作成者が多すぎない場合には、これらのアプリケーションで xsi:schemaLocation に頼ることができます。

  • RELAX NG は、XMLSchemaの代わりになるものです。

  • Roger Costello氏の著作『 XML Schemas: Best Practices 』では、Venetian Blind (ベネチアン・ブラインド) やRussian Doll (ロシア人形) といったエキゾチックな名前で、様々な設計テクニックについて論じられています。

  • XMLおよび関連テクノロジーのIBM認証開発者 になる方法についてはこちらを参照してください。

著者について

Benoit Marchal

Benoit Marchal氏は、ベルギーのナミュールを拠点にしたコンサルタントおよび著述家です。彼の著作には、 XML by Example(Que社、邦訳: インプレス社「実例で学ぶXML」。間もなく第2版が出版される予定です)、 Applied XML Solutions および XML and the Enterprise があります。また、Gamelanのコラムや、developerWorks XML zoneのコラムWorking XML の著者でもあります。最新プロジェクトの詳細については、www.marchal.com をご覧ください。

不正使用の報告のヘルプ

不正使用の報告

ありがとうございます。 このエントリーは、モデレーターの注目フラグが設定されました。


不正使用の報告のヘルプ

不正使用の報告

不正使用の報告の送信に失敗しました。


developerWorks: サイン・イン


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 利用条件

 


お客様が developerWorks に初めてサインインすると、プロフィールが作成されます。 プロフィールで選択した情報は公開されますが、いつでもその情報を編集できます。 お客様の姓名(非表示設定にしていない限り)とディスプレイ・ネームは、投稿するコンテンツと一緒に表示されます。

表示名をお選びください

developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

(半角英数字で3文字以上31文字以下にする必要があります)


「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 利用条件

 


この記事を評価する

コメント

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=XML
ArticleID=242716
ArticleTitle=ヒント: パーサにどこでスキーマを探せばよいかを教える
publish-date=05222003
author1-email=bmarchal@pineapplesoft.com
author1-email-cc=dwxed@us.ibm.com

タグ

Help
このタグで、My developerWorks のすべてのタイプのコンテンツを見つけるために検索フィールドを使用します。

スライダーバーを使用することで、より多く(少なく)タグを表示します。

人気のタグは、この特定のコンテンツ・ゾーン(例えば、Java テクノロジー、Linux や WebSphere など)に対するトップのタグを表示します。

マイ・タグは、この特定のコンテンツ・ゾーン(例えば、Java テクノロジー、Linux や WebSphere など)に対するお客様ご自身のタグを表示します。

このタグで、My developerWorks のすべてのタイプのコンテンツを見つけるために検索フィールドを使用します。人気のタグは、この特定のコンテンツ・ゾーン(例えば、Java テクノロジー、Linux や WebSphere など)に対するトップのタグを表示します。マイ・タグは、この特定のコンテンツ・ゾーン(例えば、Java テクノロジー、Linux や WebSphere など)に対するお客様ご自身のタグを表示します。