IBM®
本文へジャンプ
    Japan [変更]    ご利用条件
 
 
検索範囲検索:    
    ホーム    製品    サービス & ソリューション    サポート & ダウンロード    マイアカウント    
skip to main content

developerWorks Japan  >  XML | Java technology  >

JAXPのすべて 第1回

解析と検証を容易にするXML処理ツールキット

developerWorks
ページオプション

JavaScript を要するドキュメントオプションは表示されません

サンプルコード

原文はこちら

原文はこちら


レベル: 初級

Brett D. McLaughlin, Sr., Author and Editor, O'Reilly Media, Inc.

2005年 5月 07日

Java API for XML Processing(JAXP)では、さまざまなAPIを使用してXMLの検証、解析、変換を行うことができます。JAXPは使いやすく、ベンダー中立です。JAXPを紹介する2回シリーズの第1回であるこの記事では、このAPIの解析および検証機能を活用する方法について説明します。第2回では、JAXPを使用したXSL変換について述べます。

JavaテクノロジーとXMLは、過去5年間のプログラミングの発展の中で、おそらく最も重要なものです。結果として、Java言語でXMLを扱うためのAPIが急増しました。最も人気の高い2つ、すなわち、Document Object Model(DOM)とSimple API for XML(SAX)は多大な関心を集め、JDOMとデータバインディングAPIがそのあとに続いています(参考文献を参照)。これらのAPIの1つか2つを完全に理解するのは、かなり大変です。すべてのAPIを正しく使えたら、グールーになれます。しかし、SAXとDOMに関する深い知識はもはや必要ないと考えるJava開発者が増えています。その大部分がSun MicrosystemsのJAXPツールキットのおかげです。Java API for XML Processing(JAXP)は、初心者のJavaプログラマーにとってもXMLを管理しやすいものにするだけでなく、上級者にも多くのメリットを提供します。とは言うものの、上級者でも、JAXPについては、自分たちが依存しているAPIそのものについて誤解していることが少なくありません。

この記事は、読者にSAXおよびDOMの基本的な知識があることを前提としています。XML解析に不慣れな場合は、まず、オンライン・ソースや私の本(参考文献を参照)を流し読みして、SAXとDOMの勉強を少しした方がよいかもしれません。コールバックやDOMのノードに精通している必要はありませんが、少なくともSAXとDOMが解析APIであることは理解している必要があります。それらの違いについて、ある程度理解しておくことも重要です。これらの基本的なことを理解していれば、この記事が分かりやすくなるでしょう。

JAXP:API、それとも抽象化?

厳密に言うと、JAXPはAPIですが、抽象化層という方が正確です。XMLを解析するための新しい手段を提供するわけでも、SAXやDOMに何かを追加するわけでも、JavaとXMLの取り扱いに新しい機能を与えるわけでもありません。(この点に疑問がある人こそ、この記事を読んでください。)そうではなく、JAXPは、DOMとSAXを使用して何か難しいタスクを処理するときに、その作業を容易にします。DOMおよびSAX APIを使用しているときに遭遇する可能性のあるベンダー固有のタスクも、ベンダー中立な方法で扱えるようになります。

出世

初期バージョンのJavaプラットフォームでは、JAXPはコア・プラットフォームとは別のダウンロードでした。Java 5.0では、JAXPはJava言語の主要素になりました。最新版のJDK(参考文献を参照)を持っている人は、すでにJAXPを持っていることになります。

SAX、DOM、またはその他のXML解析APIがなければ、XMLを解析することはできません。SAX、DOM、JDOM、dom4jとJAXPとの比較に対する要求を多く見てきましたが、このような比較は不可能です。最初の4つのAPIとJAXPとでは、目的がまったく違うからです。SAX、DOM、JDOM、およびdom4jはすべて、XMLを解析します。JAXPはこれらのパーサーとそれらが公開するデータへの入り口を提供するものであり、XML文書の新しい解析方法となるわけではありません。JAXPを正しく使うためには、この違いを理解することが重要です。また、この点を理解していれば、他のXML開発者に差をつけることができるでしょう。

それでもまだ疑わしいという人は、JAXPディストリビューションを手に入れてください(出世を参照)。Webブラウザーを立ち上げて、JAXP API docsをロードします。APIの解析部分へ移動します(javax.xml.parsersパッケージにあります)。驚くべきことに、そこには6つのクラスしかありません。このAPIが難しいわけがありません。これらのクラスはすべて、既存パーサーの上に来ます。そして、そのうちの2つはエラー処理に過ぎません。JAXPは、人々が思っているよりはるかに単純なのです。では、何が混乱の原因なのでしょうか。

お山の大将

JDOMとdom4j(参考文献を参照)も、JAXPと同様、他の解析APIの上部に位置します。どちらのAPIもSAXやDOMとは違うデータ・アクセス・モデルを提供していますが、内部ではSAXを使用して(ちょっとしたトリックと修正はありますが)、ユーザーに提示するデータを入手します。

SunのJAXPとSunのパーサー

パーサーとAPIの混同の多くは、SunがJAXPとJAXPがデフォルトで使用するパーサーとをパッケージ化した方法が原因です。JAXPの初期のバージョンでは、SunはJAXP API(先ほど述べた6つのクラスと変換用のいくつかのクラスを含む)とCrimsonという名前のパーサーを含めました。Crimsonはcom.sun.xmlパッケージの一部でした。JDKに含まれる新しいバージョンのJAXPでは、SunはApache Xercesパーサー(参考文献を参照)を再パッケージ化しました。しかし、いずれにしても、パーサーはJAXPディストリビューションの一部であり、JAXP APIの一部ではありません。

こんなふうに考えてください。JDOMはApache Xercesパーサーとともに出荷されています。このパーサーはJDOMの一部ではありませんが、JDOMによって使用されるので、すぐにJDOMを使用できるように同梱されています。同じことがJAXPにも当てはまりますが、そのことが明確に公表されていません。JAXPにパーサーが付いているのは、すぐに使えるようにするためなのです。しかし、多くの人が、Sunのパーサーに含まれているクラスをJAXP APIそのものの一部であると言っています。たとえば、ニュースグループでよくある質問は、「JAXPに付いてくるXMLDocumentクラスを使うにはどうしたらよいか、何のためのものなのか」という質問です。それに対する回答は、いささか込み入っています。

(パッケージ)名の中には何があるか

初めてJava 1.5のソース・コードを開いてみたとき、私は自分が見たもの、と言うよりは、見なかったものに驚きました。Xercesは通常のパッケージ(org.apache.xerces)にありませんでした。SunはXercesクラスをcom.sun.org.apache.xerces.internalに移動していました。(これは少々失礼なことだと思うのですが、だれも私に尋ねませんでした。)何はともあれ、JDKでXercesを探すときには、ここを探してください。

まず、com.sun.xml.tree.XMLDocumentクラスはJAXPの一部ではありません。初期バージョンのJAXPにパッケージ化されていたSunのCrimsonパーサーの一部です。したがって、上記の質問は、最初から間違っています。第2に、JAXPの主な目的は、パーサーを扱うときにベンダー独立性を提供することです。JAXPでは、SunのXMLパーサー、ApacheのXerces XMLパーサー、およびOracleのXMLパーサーで同じコードを使用することができます。その場合、Sun固有のクラスを使用すると、JAXPの使用目的に反します。このテーマがいかに錯綜しているか、分かってきたのではありませんか。JAXPディストリビューションのパーサーとAPIがひとまとめにされ、一部の開発者は、一方のクラスと機能をもう一方の一部と誤解しています。

さて、待ち受ける混乱のすべてを見越すことができるようになったところで、コードと概念に話を進めましょう。




上に戻る


SAXからの出発

SAXはXMLを処理するためのイベント・ドリブンなメソドロジーです。SAXは多数のコールバックから成ります。たとえば、startElement()コールバックは、SAXパーサーがエレメントの開始タグを検出するたびに呼び出されます。文字データに対してはcharacters()コールバックが呼び出され、エレメントの終了タグに対してはendElement()が呼び出されます。文書処理、エラー、その他の字句構造のために、さらに多くのコールバックがあります。お分かりいただけましたか。SAXプログラマーは、これらのコールバックを定義するSAXインターフェースの1つを実装します。SAXには、これらのコールバックのすべてを実装して、すべてのコールバック・メソッドのデフォルトの空の実装を提供するDefaultHandler(org.xml.sax.helpersパッケージ内)というクラスもあります。(この重要性については、次のセクション「DOMの扱い」のDOMの説明の中で述べます。)SAX開発者は、このクラスを拡張するだけで、特定のロジックの挿入を必要とするメソッドを実装できます。したがって、SAXの鍵は、これらさまざまなコールバック用のコードを提供して、適切なときにそれぞれをパーサーにトリガーさせることです。典型的なSAXルーチンは、次のとおりです。

  1. 特定のベンダーのパーサー実装を使用して、SAXParserインスタンスを作成します。
  2. (たとえば、DefaultHandlerを拡張するクラスを使用して)コールバック実装を登録します。
  3. 解析を開始して、コールバック実装が作業を終えるのを待ちます。

JAXPのSAXコンポーネントは、このすべてを実行する簡単な手段となります。JAXPを使用しない場合、SAXパーサー・インスタンスをベンダー・クラス(org.apache.xerces.parsers.SAXParserなど)から直接インスタンス化するか、XMLReaderFactoryというSAXヘルパー・クラス(やはりorg.xml.sax.helpersパッケージにあります)を使用しなければなりません。最初の方法の問題点は明白です。すなわち、ベンダー中立でないことです。2番目の方法の問題点は、ファクトリーは引数として、使用するパーサー・クラスのString名を必要とすることです(Apacheクラスの場合、やはり、org.apache.xerces.parsers.SAXParser)。別のパーサー・クラスをStringとして渡すことによって、パーサーを変更できます。この方法では、パーサー名を変更した場合、インポート文を変更する必要はありませんが、それでもクラスを再コンパイルする必要があります。これが最上のソリューションでないことは明白です。クラスを再コンパイルしなくてもパーサーを変更できれば、その方がはるかに簡単です。

JAXPは、よりよい方法を可能にします。すなわち、パーサーをJavaのシステム・プロパティーとして指定することができます。もちろん、Sunからディストリビューションをダウンロードすることによって入手できるのは、SunバージョンのXercesを使用するJAXP実装です。パーサーをたとえばOracleのパーサーに変更するには、クラスパス設定を変更し、パーサー実装を別のパーサー実装に移動する必要がありますが、コードの再コンパイルは必要ありません。そして、これがJAXPのマジックであり、抽象化なのです。

ずるいSAX開発者

少し言い訳しておきます。コーディングをちょっと工夫すれば、SAXアプリケーションに、使用するパーサー・クラスをシステム・プロパティーやプロパティー・ファイルからピックアップさせることができます。しかし、JAXPを使用すれば、このような手間をまったくかけなくても同じことができるので、JAXPのルートを行った方がよいでしょう。

SAXパーサー・ファクトリーの概要

JAXPSAXParserFactoryクラスは、パーサー実装の容易な変更を可能にする鍵です。このクラスの新しいインスタンスを作成する必要があります(もう少しあとで説明します)。新しいインスタンスが作成された後、SAX対応パーサーを取得するための手段となるのがファクトリーです。舞台裏でJAXP実装がベンダー依存コードの面倒を見るので、あなたのコードが汚されることはありません。このファクトリーには、他にも優れた機能がいくつかあります。

SAXパーサーのインスタンスを作成するという基本的な仕事に加えて、このファクトリーでは構成オプションを設定することもできます。これらのオプションは、ファクトリーを通じて取得されたすべてのパーサー・インスタンスに影響します。JAXP 1.3で最もよく使われる2つのオプションは、setNamespaceAware(boolean awareness)による名前空間対応の設定とsetValidating(boolean validating)によるDTD検証の有効化です。これらのオプションが設定されると、メソッド呼び出し後にファクトリーから取得されたすべてのインスタンスに影響を与えることを忘れないでください。

ファクトリーをセットアップした後、newSAXParser()を呼び出すと、すぐに使えるJAXPSAXParserクラスのインスタンスが返されます。このクラスは、基本のSAXパーサー(SAXクラスorg.xml.sax.XMLReaderのインスタンス)をラップします。また、パーサー・クラスへのベンダー固有の追加を使用しないように保護します。(この記事のXmlDocumentクラスの説明を覚えていますか。)このクラスによって、実際の解析動作を開始することができます。リスト1に、SAXファクトリーの作成、構成、および使用方法を示します。


リスト1.SAXParserFactoryの使用
                
import java.io.OutputStreamWriter;
import java.io.Writer;
// JAXP
import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.parsers.SAXParser;
// SAX
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class TestSAXParsing {
    public static void main(String[] args) {
        try {
            if (args.length != 1) {
                System.err.println ("Usage: java TestSAXParsing [filename]");
                System.exit (1);
            }
            // Get SAX Parser Factory
            SAXParserFactory factory = SAXParserFactory.newInstance();
            // Turn on validation, and turn off namespaces
            factory.setValidating(true);
            factory.setNamespaceAware(false);
            SAXParser parser = factory.newSAXParser();
            parser.parse(new File(args[0]), new MyHandler());
        } catch (ParserConfigurationException e) {
            System.out.println("The underlying parser does not support " +
                               " the requested features.");
        } catch (FactoryConfigurationError e) {
            System.out.println("Error occurred obtaining SAX Parser Factory.");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
class MyHandler extends DefaultHandler {
    // SAX callback implementations from ContentHandler, ErrorHandler, etc.
}

リスト1を見ると、ファクトリーの使用に際してJAXP固有の2つの問題が発生する恐れがあることが分かります。すなわち、SAXファクトリーを取得または構成できないことと、SAXパーサーを構成できないことです。最初の問題は、FactoryConfigurationErrorによって表され、通常、JAXP実装またはシステム・プロパティーで指定されたパーサーを取得できないときに発生します。2番目の問題はParserConfigurationExceptionによって表され、使用されているパーサーでは要求された機能を使用できないときに発生します。どちらも簡単に対処できるので、これによってJAXPの使用が難しくなるわけではありません。実際、いくつかの機能を設定し、特定の機能が使用できない状況をグレースフルに処理するコードを書くとよいかもしれません。

SAXParserインスタンスは、ファクトリーをgetしたときに取得され、名前空間サポートをオフにし、検証をオンにします。その後、解析が始まります。SAXパーサーのparse()メソッドは、カスタム・ハンドラー・クラスで拡張する前述のSAXHandlerBaseヘルパー・クラスのインスタンスを取ります。このクラスの実装と完全なJavaリストを確認するには、コード・ディストリビューションを参照してください(ダウンロードを参照)。解析するFileも渡します。ただし、SAXParserクラスには、この単純なメソッド以外にもさまざまなメソッドが含まれています。

SAXパーサーでの作業

SAXParserクラスのインスタンスを作成した後は、解析するFileを渡すだけでなく、他にもいろいろなことができます。大規模アプリケーションのコンポーネントが通信する方法により、オブジェクト・インスタンスの作成者がその使用者であると仮定するのは安全ではない場合があります。あるコンポーネントがSAXParserインスタンスを作成するときに、別のコンポーネント(おそらく別の開発者によってコード化されたコンポーネント)が同じインスタンスを使用する必要があるかもしれません。この理由から、JAXPにはパーサーの設定を調べるメソッドがあります。たとえば、isValidating()を使用して、パーサーが検証を実行するかどうかを調べることができ、isNamespaceAware()を使用して、パーサーがXML文書の名前空間を処理できるかどうかを調べることができます。これらのメソッドによってパーサーに何ができるかを知ることができますが、SAXParserインスタンスだけを使用して、SAXParserFactoryそのものを使用しなかった場合は、これらの機能を変更する手段がありません。これはパーサー・ファクトリー・レベルで行う必要があります。

文書の解析を要求する方法もいろいろあります。FileおよびSAXDefaultHandlerインスタンスを受け入れるだけでなく、SAXParserのparse()メソッドは、SAXInputSource、JavaInputStream、またはString形式のURLを、すべてDefaultHandlerインスタンスとともに受け入れることができます。したがって、さまざまな形式でラップされた文書を解析することができます。

最後に、基本のSAXパーサー(org.xml.sax.XMLReaderのインスタンス)を入手して、それをSAXParsergetXMLReader()メソッドを通じて直接使用することができます。この基本インスタンスを取得すると、通常のSAXメソッドが使用可能です。リスト2に、JAXPにおけるSAX解析の中核的クラスであるSAXParserクラスのさまざまな使用例を示します。


リスト2. JAXPSAXParserクラスの使用
                
// Get a SAX Parser instance
SAXParser saxParser = saxFactory.newSAXParser();
// Find out if validation is supported
boolean isValidating = saxParser.isValidating();
// Find out if namespaces are supported
boolean isNamespaceAware = saxParser.isNamespaceAware();
// Parse, in a variety of ways
// Use a file and a SAX DefaultHandler instance
saxParser.parse(new File(args[0]), myDefaultHandlerInstance);
// Use a SAX InputSource and a SAX DefaultHandler instance
saxParser.parse(mySaxInputSource, myDefaultHandlerInstance);
// Use an InputStream and a SAX DefaultHandler instance
saxParser.parse(myInputStream, myDefaultHandlerInstance);
// Use a URI and a SAX DefaultHandler instance
saxParser.parse("http://www.newInstance.com/xml/doc.xml",
                myDefaultHandlerInstance);
// Get the underlying (wrapped) SAX parser
org.xml.sax.XMLReader parser = saxParser.getXMLReader();
// Use the underlying parser
parser.setContentHandler(myContentHandlerInstance);
parser.setErrorHandler(myErrorHandlerInstance);
parser.parse(new org.xml.sax.InputSource(args[0]));

ここまで、SAXについて色々話してきましたが、驚くようなことは何もなかったはずです。JAXPによって追加された機能性は、特にSAXに関しては、かなり些細なものです。この些細な機能性が、あなたのコードの移植性を高めて、SAX互換のXMLパーサーで自由に、または商業的に、他の開発者も使えるようにします。それだけのことです。JAXPでのSAXの使用には、それ以上のことは何もありません。すでにSAXを知っている人は、道のりのほぼ98パーセントは済んでいることになります。あとは、2つのクラスといくつかのJava例外を覚えるだけです。SAXを使ったことがないという人も、簡単ですから、すぐに覚えられます。




上に戻る


DOMの扱い

DOMという難題に取り掛かる前に休憩が必要だと思う人は、どうぞ、少し休んでください。JAXPでのDOMの使用は、SAXでの使用とほとんど同じです。2つのクラス名と戻り型を変更するだけです。SAXがどのように機能し、DOMとは何かということが理解できていれば、何も問題はありません。

DOMとSAXの主な違いは、APIそのものの構造にあります。SAXはイベント・ベースのコールバックのセットで構成されているのに対して、DOMはメモリー内ツリー構造です。SAXには、(開発者が手動で作成しない限り)作用対象となるデータ構造はありません。したがって、SAXではXML文書を修正することはできません。DOMには、この機能があります。org.w3c.dom.DocumentクラスはXML文書を表し、要素、属性、およびその他のXML構造体を表すDOMノードで構成されています。したがって、JAXPからSAXコールバックをfireする必要はありません。JAXPの役目は、解析からDOMDocumentオブジェクトを返すことだけです。

DOMパーサー・ファクトリーの概要

DOMの基本とDOMとSAXの違いさえ理解していれば、それ以上知るべきことはありません。リスト3のコードは、リスト1のSAXのコードに驚くほど似ています。まず、(リスト1のSAXParserFactoryと同じように)DocumentBuilderFactoryが取得されます。次に、(SAXでと同じように)検証と名前空間を処理するようにファクトリーが構成されます。次に、(もうお分かりのように、やはり同じように)DocumentBuilderインスタンス(SAXParserに相当)がファクトリーから取得されます。その後、解析が行われて、結果のDOMDocumentオブジェクトがDOMツリーを表示するメソッドに渡されます。


リスト3. DocumentBuilderFactoryの使用
                
import java.io.File;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
// JAXP
import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
// DOM
import org.w3c.dom.Document;
import org.w3c.dom.DocumentType;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class TestDOMParsing {
    public static void main(String[] args) {
        try {
            if (args.length != 1) {
                System.err.println ("Usage: java TestDOMParsing " +
                                    "[filename]");
                System.exit (1);
            }
            // Get Document Builder Factory
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            // Turn on validation, and turn off namespaces
            factory.setValidating(true);
            factory.setNamespaceAware(false);
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document doc = builder.parse(new File(args[0]));
            // Print the document from the DOM tree and
            //   feed it an initial indentation of nothing
            printNode(doc, "");
        } catch (ParserConfigurationException e) {
            System.out.println("The underlying parser does not " +
                               "support the requested features.");
        } catch (FactoryConfigurationError e) {
            System.out.println("Error occurred obtaining Document " +
                               "Builder Factory.");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    private static void printNode(Node node, String indent)  {
        // print the DOM tree
    }
}

このコードでは(JAXPでのSAXと同様に)2つの問題が発生することがあります。すなわち、FactoryConfigurationErrorParserConfigurationExceptionです。それぞれの原因は、SAXの場合と同じです。実装クラスに問題があるか(FactoryConfigurationError)、要求された機能をパーサーがサポートしていないか(ParserConfigurationException)のいずれかです。この点でのDOMとSAXの唯一の違いは、DOMでは、SAXParserFactoryの代わりにDocumentBuilderFactoryを、SAXParserの代わりにDocumentBuilderを使用することです。それだけです。(DOMツリーを表示するために使用されるメソッドも含めて、完全なコード・リストを見たい場合は、ダウンロードを参照してください。)

DOMパーサーでの作業

DOMファクトリーがあれば、DocumentBuilderインスタンスを取得できます。DocumentBuilderインスタンスから使用できるメソッドは、SAXParserから使用できるメソッドとほぼ同じです。主な違いは、parse()メソッドの変化形はSAXDefaultHandlerクラスのインスタンスを取らないことです。代わりに、解析されたXML文書を表すDOMDocumentインスタンスを返します。その他の唯一の違いは、SAXと同様の機能を提供する2つのメソッドが用意されていることです。

  • setErrorHandler()は、SAXErrorHandler実装を取り、解析中に発生する問題を処理します。
  • setEntityResolver()は、SAXEntityResolver実装を取り、エンティティー解決を処理します。

リスト4に、これらのメソッドの使用例を示します。


リスト4. JAXPDocumentBuilderクラスの使用
                
// Get a DocumentBuilder instance
DocumentBuilder builder = builderFactory.newDocumentBuilder();
// Find out if validation is supported
boolean isValidating = builder.isValidating();
// Find out if namespaces are supported
boolean isNamespaceAware = builder.isNamespaceAware();
// Set a SAX ErrorHandler
builder.setErrorHandler(myErrorHandlerImpl);
// Set a SAX EntityResolver
builder.setEntityResolver(myEntityResolverImpl);
// Parse, in a variety of ways
// Use a file
Document doc = builder.parse(new File(args[0]));
// Use a SAX InputSource
Document doc = builder.parse(mySaxInputSource);
// Use an InputStream
Document doc = builder.parse(myInputStream, myDefaultHandlerInstance);
// Use a URI 
Document doc = builder.parse("http://www.newInstance.com/xml/doc.xml");

DOMについてのこのセクションを読むのに少し退屈してきましたか。あなただけではありません。書いている私も少し退屈です。と言うのも、SAXについて学んだことをDOMに応用するのは、実に簡単なことだからです。




上に戻る


検証の実行

Java 5.0(およびJAXP 1.3)で、JAXPは文書を検証する新しい方法を導入しました。単にSAXまたはDOMファクトリーのsetValidating()メソッドを使用するのではなく、検証が新しいjavax.xml.validationパッケージ内のいくつかのクラスに分けられています。W3C XML Schema、DTD、RELAX NGスキーマ、およびその他の制約モデルも含めて、検証のニュアンスのすべてを詳しく述べるには、この記事のスペースでは足りませんが、すでに制約をある程度理解している人なら、新しい検証モデルを使用して、文書が制約に合致していることを確認するのは、かなり容易です。

冗長性は常に良いとは限らない

してはならないことのひとつは、setValidating(true)javax.xml.validationパッケージを使用することです。厄介なエラーが発生して、そのほとんどが追跡困難です。setValidating()を呼び出さずに(デフォルトでfalseになっています)、代わりに新しいJAXP検証フレームワークを使用するのを習慣にすると良いでしょう。

まず、制約モデル(おそらくはディスク上のファイル)をJAXPで使用できる形式に変換します。そのファイルをSourceインスタンスにロードします。(Sourceについては第2回で詳しく述べます。とりあえず、ディスク上の文書をDOMDocumentとして、またはその他ほとんどなんでも表すということだけ覚えておいてください。)次に、SchemaFactoryを作成して、SchemaFactory.newSchema(Source)を使用してスキーマをロードすると、新しいSchemaオブジェクトが返されます。最後に、このSchemaオブジェクトとSchema.newValidator()で新しいValidatorオブジェクトを作成します。リスト5を見ていただくと、今の説明がよく分かると思います。


リスト5. JAXP検証フレームワークの使用
                
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(new File(args[0]));
// Handle validation
SchemaFactory constraintFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Source constraints = new StreamSource(new File(args[1]));
Schema schema = constraintFactory.newSchema(constraints);
Validator validator = schema.newValidator();
// Validate the DOM tree
try {
    validator.validate(new DOMSource(doc));
    System.out.println("Document validates fine.");
} catch (org.xml.sax.SAXException e) {
    System.out.println("Validation error: " + e.getMessage());
}

これは、こつさえ分かれば、かなり簡単です。このコードを自分で入力するか、または完全なリストを参照してください(ダウンロードを参照)。




上に戻る


パーサーの変更

JAXPファクトリーのクラスが使用するパーサーは、簡単に変更できます。パーサーの変更は、実際にはパーサー・ファクトリーを変更することを意味します。すべてのSAXParserおよびDocumentBuilderインスタンスは、これらのファクトリーから派生されたものだからです。どのパーサーがロードされるかはファクトリーによって決まるので、変更しなければならないのはファクトリーです。SAXParserFactoryインターフェースの実装を変更するには、Javaシステム・プロパティーjavax.xml.parsers.SAXParserFactoryを設定します。このプロパティーが定義されていない場合は、デフォルトの実装(ベンダーが指定したもの)が返されます。DocumentBuilderFactory実装についても同様です。この場合は、javax.xml.parsers.DocumentBuilderFactoryシステム・プロパティーが照会されます。




上に戻る


まとめ

この記事を読んで、JAXPのほぼ全景が把握できたと思います。

  • SAXを利用できること
  • DOMを利用できること
  • パーサーを簡単に変更できること

JAXPの解析機能と検証機能を理解するには、ほんの少し苦労しなければなりません。JAXPを使えるようになるための最も難しい部分は、システム・プロパティーを変更すること、パーサーまたはビルダーではなくファクトリーから検証を設定すること、そしてどの部分がJAXPではないかを明確に理解することです。JAXPは、任意のある2つのJavaおよびXML API以上に役立つプラグ可能性レイヤーとなります。みなさんのコードをベンダー中立にして、解析コードを再コンパイルしなくても別のパーサーに変更できるようにします。ですから、JAXPをダウンロードして、がんばってみましょう。第2回では、JAXPがXML文書の変換にどのように役立つかを説明します。





上に戻る


ダウンロード

内容ファイル名サイズダウンロード形式
Sample code for All about JAXPx-jaxp-all-about.zip5KBHTTP
ダウンロード形式について


参考文献

  • XMLとJava技術を使って作業する上でのヒントを得るために、Brett McLaughlinがホストしている「XML and Java technology」フォーラムを見てください。

  • SunのJava and XML headquartersで、JAXPについて、さらに学んでください。

  • Javaプログラミングが初めての人は、Java 5.0をダウンロードすれば、JDKと一緒にJAXPも入手することができます。

  • JAXP 1.3の新しい機能を詳しく知るために、developerWorksにある2回シリーズの記事、「JAXP 1.3は何が新しいのか?」を読んでください。
    • 第1回(2004年11月)は、JAXP仕様の概要を簡単に説明し、javax.xml.parsersパッケージに加えられた修正の詳細や、強力なスキーマ・キャッシュや妥当性検証フレームワークについて説明しています。
    • 第2回(2004年12月)は、XML仕様の名前空間で定義される概念のサポートを追加するユーティリティーに触れ、javax.xml.transformパッケージに加えられた変更を説明しています。

  • JAXPの下に隠されたAPIについて、さらに学んでください。最初はSAXのWebサイトでSAX 2 for Javaを、次にW3CのWebサイトでDOMを見てください。

  • Apache XercesパーサーのJDK 5.0実装をダウンロードしてください。

  • SAXでベンダー非依存性を実現する」(developerWorks, 2001年3月)を読んで、SAXベースのアプリケーションでSAXやSAXヘルパー・クラスを使ってベンダー非依存性を実現する方法を学んでください。

  • JDOMについて、さらに学んでください。JDOMは、Java言語の中でXML文書を容易に効率良く読み、書き、操作できるように表現するためのオープン・ソースのツールキットです。

  • JDOMでXMLプログラミングを単純化する」(developerWorks, 2001年5月)を読んでください。JDOMによって、XML文書操作がどれほど楽になるかが分かります。

  • dom4jを調べてください。dom4jは、Javaプラットフォーム上でXMLやXPath、XSLTを扱うための、オープン・ソースのライブラリーです。

  • Brett McLaughlin著のJava & XML(2001年O'Reilly & Associates刊)を読んでください。JavaプログラマーがXMLを使ってWebベースの企業アプリケーションを構築する方法を説明しています。

  • Doug TidwellによるdeveloperWorksのチュートリアル「XML programming in Java technology, Part 1」(2004年1月)を読んで、Java技術を使ってXML文書を操作するための基礎を学んでください。Part 2(2004年7月)は、名前空間の取り扱い、XML文書の妥当性検証、典型的XML文書無しでのXML構造構築など、より難しい話題を取り上げています。Part 3(2004年7月)は、XMLデータ構造の生成、こうした構造の操作、XMLパーサーと非XMLデータ・ソースとのインターフェースなど、さらに高度な課題を解説しています。

  • XMLについて、もっと基本的なことが必要であれば、developerWorksのIntro to XML tutorial(2002年8月)や、その他の教育資料を試してください。これらは最も基本的な話題を網羅しています。

  • developerWorksのDeveloper Bookstoreには、広範な話題を網羅したXML関連の書籍が取り揃えられていますので、ぜひご利用ください。


著者について

Photo of Brett McLaughlin

Brett McLaughlin氏は、Logo (小さな三角形を覚えていますか?) の時代からコンピューターの仕事をしています。現在の専門は、JavaおよびJava関連のテクノロジーを使ったアプリケーション・インフラストラクチャーの構築です。ここ数年は、Nextel Communications and Allegiance Telecom, Inc. でこれらのインフラストラクチャーの実装に携わっています。Brett氏は、Javaサーブレットを使ってWebアプリケーション開発のための再利用可能なコンポーネント・アーキテクチャーを構築するJava ApacheプロジェクトTurbineの共同設立者の1人です。同氏はまた、オープン・ソースのEJBアプリケーション・サーバーであるEJBossプロジェクトと、オープン・ソースのXML Web公開エンジンであるCocoonにも貢献しています。




記事の評価


サイト改善のため、ご意見をお寄せください。こちらのフォームからお願いいたします。



 


 


不充分・不完全である大変素晴らしい
 


この記事を共有する

del.icio.us del.icio.us newsing newsing FC2ブックマーク FC2ブックマーク
Choix! Choix! ニフティクリップ ニフティクリップ Yahoo!ブックマーク Yahoo!ブックマーク
MM/memo MM/memo CZブックマーク CZブックマーク livedoorクリップ livedoorクリップ
はてなブックマーク はてなブックマーク Buzzurl(バザール) Buzzurl(バザール)




上に戻る


    日本IBMについて プライバシー お問い合わせ