Javaを紐解くための重点キーワード

吉田哲也
アプレッソ
2001/7/6


JAXP(Java API for XML Parsing)


JAXPとは?

 JAXP 1.0は、JCP(Java Community Process)にJSR#005として提出されたものが最終仕様として公開されたものだ。JAXP 1.0はJava API for XML Parsingの略で、XMLドキュメントをParsing(解析)するためのJavaのAPIである。

 JAXP 1.0はSAX 1.0、DOM level1をサポートしている。JAXP の特徴は、「Plugability」という言葉に集約される。この「Plugability」については後述する。また、JAXP 1.1はJCP にJSR#063として提出され、最終仕様として2001年2 月12日に公開された。JAXP 1.1はJava API for XML Processingという名称に変更になり、XML ドキュメントをParsing するためのものからProcessing(処理)するためのものになっている。これは、XSLTのAPIが付け加わったからで、これがJAXP 1.0とJAXP 1.1の最大の違いだ。主な違いを以下に示す。

  • XSLT 1.0 のサポート
  • SAX 2.0 のサポート
  • DOM Level2 のサポート

 また、JAXP 1.1の参照実装(Reference Implementation)は、デフォルトでは、SAX、DOMのパーサはSun MicrosystemsのProject Xから派生したCrimsonを使用し、XSLT エンジンはXalan を使用している。

JAXPの Plugability

 JAXPはバージョン1.0のときから「Plugability」ということに重点を置いている。アプリケーションからはJAXPのインターフェイスを介することによってパーサの実装を選択できるということだ(図1)

図1 JAXPインターフェイスを介することで、パーさを自由に選択できる

 SAXやDOMの仕様に準拠しているパーサ(JAXP標準のパーサやXercesやXalanなど)ならば、抽象的なjavax.xml.parsersjavax.xml.transform APIを通して使用することができる。

SAX

 SAX自体についての説明は、http://megginson.com/SAX/を参照してほしい。ここでは JAXPでのSAXについて説明する。SAXPaserのインスタンスを得る手順は以下のようになる。

  1. SAXParserFactoryクラスのstaticメソッドのnewInstanceによって、SAXPaserFactoryインスタンスを獲得する
  2. その獲得したSAXPaserFactoryインスタンスからSAXPaserを作る

 SAXParserFactoryクラスのnewInstanceメソッドは以下の順序で SAXParserFactoryを決定する。この部分が「plugability」を実現する部分だ。

  1. javax.xml.parsers.SAXParserFactory システムプロパティを使う
  2. JRE ディレクトリ中のプロパティファイル lib/jaxp.properties を使う。このファイルの中に上記のシステムプロパティのキーと、バリューとなる SAX パーサの実装クラスを記述する
  3. Service API を使う。Jar ファイル中の WEB-INF/services/javax.xml.parsers.parsers.SAXParserFactoryファイルに記述されているクラスを使う
  4. デフォルトのSAXParserFactoryインスタンスを使用する

 以下にSAXParserを作成するサンプルプログラムを示す。XMLファイルの中の開始タグの名前と終了タグの名前を表示する。第1引数にはパースしたいXMLファイルを指定する。

// SAXTest.java

import javax.xml.parsers.*;
import org.xml.sax.*;
import org.xml.sax.helpers.*;
import java.io.*;


public class SAXTest {
  public static void main (String[] args) {
  // どの Factory インスタンスを使用するのかを表示
  System.out.println(System.getProperty(
     "javax.xml.parsers.SAXParserFactory"));

    try {
      // SAXParserFactory インスタンスを取得
      SAXParserFactory factory =
         SAXParserFactory.newInstance();

      // デフォルトのイベントハンドラを作成
      DefaultHandler handler = new MyHandler();

      // SAXParser を取得
      SAXParser parser = factory.newSAXParser();

      // myHandler を用いて parse する
      parser.parse(new InputSource(args[0]), handler);
    }
    catch (SAXException e) {
      System.out.println("SAXException");
    }
    catch (IOException e) {
      System.out.println("IOException");
    }
      catch (ParserConfigurationException e) {
      System.out.println("ParserConfigurationException");
    }
  }
}

class MyHandler extends DefaultHandler {
  public void startElement (String uri,
    String name,
    String qName,
    Attributes atts) {
    System.out.println("Start Element : " + name);
  }

  public void endElement (String uri,
    String name,
    String qName) {
    System.out.println("End Element : " + name);
  }
}

 上記の例ではデフォルトのパーサを使用しているが、以下のように起動するとコードの変更なしにXercesのパーサを使用できる。

java -Djavax.xml.parsers.SAXParserFactory=
org.apache.xerces.jaxp.SAXPaserFactoryImpl SAXTest xml_file

DOM

 DOM自体の説明についてはW3Cのページなどを参照してほしい(http://www.w3.org/DOM/)。

 DOMのパーサについてもSAXのときと同様だ。org.w3c.dom.Documentオブジェクトを得るためにDOMの実装をラップしたDocumentBuilderを使用する。そのDocumentBuilderのインスタンスを作成する手順は以下のようになる。

  1. DocumentBuilderFactoryクラスのstaticメソッドのnewInstance によってDocumentBuilderFactoryインスタンスを取得する
  2. その獲得したDocumentBuilderFactoryインスタンスからDoucumentBuilderを作成する

 DocumentBuilderFactoryクラスのnewInstanceメソッドは以下の順序でDocumentBuilderFactoryを決定する。

  1. javax.xml.parsers.DocumentBuilderFactoryシステムプロパティを使う
  2. JRE ディレクトリ中のプロパティファイル lib/jaxp.properties を使う。このファイルの中に上記のシステムプロパティのキーと、バリューとなるDOM パーサの実装クラスを記述する
  3. Service API を使う。Jar ファイル中の WEB-INF/services/javax.xml.parsers.parsers.DocumentBuilderFactory ファイルに
    記述されているクラスを使う
  4. デフォルトのDocumentBuiderFactoryインスタンスを使用する

 ここでも簡単なサンプルプログラムを示す。このサンプルプログラムは単にルートノードのタグ名を表示するだけのプログラムである。第1引数にはパースしたい XML ファイルを指定する。

// DOMTest.java

import javax.xml.parsers.*;
import org.w3c.dom.*;
import org.xml.sax.*;
import java.io.*;

public class DOMTest {
  public static void main (String[] args) {
  // どの Factory インスタンスを使用するのかを表示
  System.out.println(System.getProperty(
  "javax.xml.parsers.DocumentBuilderFactory"));

    try {
      // DocumentBuilderFactory インスタンスを取得
      DocumentBuilderFactory factory =
          DocumentBuilderFactory.newInstance();

      // DocumentBuilder を取得
      DocumentBuilder builder =
      factory.newDocumentBuilder();

      // DocumentBuilder を用いて Document オブジェクトを取得
      Document doc =
      builder.parse(new InputSource(args[0]));

      // ルートノードのタグ名を表示
      System.out.println(
      doc.getDocumentElement().getTagName());
    }
    catch (SAXException e) {
      System.out.println("SAXException");
    }
    catch (IOException e) {
      System.out.println("IOException");
    }
    catch (ParserConfigurationException e) {
      System.out.println(
        "ParserConfigurationException");
    }
  }
}

 もちろんこの例でも、コードの変更なしにxercesのパーサを使用できる。システムプロパティにxercesのDOMパーサを設定している。

java -Djavax.xml.parsers.DocumentBuilderFactory=
org.apache.xerces.jaxp.DocumentBuilderFactoryImpl DOMTest xml_file

XSLT

 XSLTについても仕様は
http://www.w3.org/TR/1999/REC-xslt-19991116を参照してほしい。JAXPにおいてXSLTを行うにはjavax.xml.transform.Transformerクラスを使う。SAXやDOMのときと同じようにTransformerインスタンスを取得するためにTransformerFactoryクラスから取得する。手順は以下のとおりだ。

  1. TransformerFactoryクラスの static メソッドのnewInstanceによってTransformerFactoryインスタンスを取得する
  2. その獲得したTransformerFactoryインスタンスに XSLT が記述されたスタイルシートをセットする
  3. そのスタイルシートをもとにしたTransformerインスタンスを取得する

 XSLTについてもPlugabilityを確保する。TransformerFactoryクラスの newInstanceメソッドは以下の順序でインスタンスを決定する。

  1. DocumentBuilderFactoryクラスのstaticメソッドのnewInstanceによってDocumentBuilderFactoryインスタンスを取得する
  2. その獲得したDocumentBuilderFactoryインスタンスからDoucumentBuilderを作成する

 DocumentBuilderFactoryクラスのnewInstanceメソッドは以下の順序でDocumentBuilderFactoryを決定する。

  1. javax.xml.transformer.TransformerFactoryシステムプロパティを使う
  2. JREディレクトリ中のプロパティファイル lib/jaxp.properties を使う。このファイルの中に上記のシステムプロパティのキーと、バリューとなる実装クラスを記述する。
  3. Service API を使う。Jar ファイル中の WEB-INF/services/javax.xml.transformer.TransformerFactory ファイルに記述されているクラスを使う
  4. デフォルトのDocumentBuilderFactoryインスタンスを使用する

 以下に簡単な XSLT を行うサンプルプログラムを示す。このサンプルプログラムは第1引数にXSLTをかけたいXML ドキュメント、第2引数にXSLTが記述されたスタイルシートを取る。そしてその結果を標準出力に出力する。

// XSLTTest.java

import java.io.*;
import java.util.*;
import javax.xml.transform.*;
import javax.xml.transform.stream.*;


class XSLTTest {
  public static void main(String args[]) {
    try {
      // TransfomerFactory インスタンスの取得
      TransformerFactory factory =
        TransformerFactory.newInstance();

      // XSL をセット
      StreamSource xslsrc =
      new StreamSource(new FileInputStream(args[1]));

      // セットされた XSL から Transformar を取得
      Transformer transformer =
        factory.newTransformer(xslsrc);

      // 出力のエンコーディングをシフト JIS にセット
      transformer.setOutputProperties(new Properties() {
        {
      setProperty("encoding", "Shift_JIS");
        }
      });

      // XSLT をかける XML をセット
      StreamSource xmlsrc = new StreamSource(
       new FileInputStream(args[0]));

      // XSLT をかけ,出力を標準出力に
    transformer.transform(
     xmlsrc, new StreamResult(System.out));

    }
    catch (TransformerException e) {
       System.out.println("TransformerException");
    }
    catch (IOException e) {
      System.out.println("IOException");
    }
  }
}

 JAXP 1.1において、SAXパーサやDOMパーサ、XSLTエンジンをどのように作成するのかに重点をおいて説明した。JAXP 1.1はここに述べた限りではない。しかし、ここに述べた内容は、JAXPを使用する場合には確実に必要となる。

 

Javaを紐解くための重点キーワード

 

 



Java Agile フォーラム 新着記事
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Java Agile 記事ランキング

本日 月間