revised: Nov./16th/2003
JAXPでは、XSLTを処理するために、ストリーム、DOM、SAX用の三つのパッケージと、これらに共通する上位のパッケージを提供しています。
javax.xml.transform...汎用APIjavax.xml.transform.dom...DOM用APIjavax.xml.transform.sax...SAX用APIjavax.xml.transform.stream...ストリームおよびURI用APIリスト3 (XSLTDemo.java)では、ストリームによるXSLTの処理の例を挙げました。ここでは、ソースツリーとXSLT文書を受け取るための javax.xml.transform.stream.StreamSource と、結果ツリーを受け取る javax.xml.transform.stream.StreamResult を定義し、XSLTプロセッサを抽象化する javax.xml.transform.Transformer とそのファクトリー・クラス javax.xml.transform.TransformerFactory で入出力を行っていました。
DOMの場合は、DOMSource と DOMResult を使って、DOMツリーである Document オブジェクトに入出力します。ストリームとDOMでは、入出力対象がデバイスかDOMツリーであるかの相違しかありません。SAXの場合も、SAXSource と SAXResult により入出力を制御できますが、イベント駆動型であるために、ハンドラによる処理が必要になり、ストリームやDOMに比べると、やや複雑です。
リスト11は、DOMベースのXSLT処理用のコードです。この例では、最初にXSLTとソースXMLの2つのDocumentオブジェクトでつくり、これを引数にして、DOMSourceオブジェクトxslSrcとsourceを生成しています。DOMResultオブジェクトresultは、最初は空っぽで生成しています。続いて、XSLTプロセッサtransformerをファクトリtFactoryから生成し、メソッドtranform()で実際に変換が行われるとresultに結果ツリーが書き込まれます。
リスト11の後半は、DOMツリーの出力用のコードです。DOM level 1, level 2では、シリアライズのAPIは提供されていません。ここでは、DOMResultから取り出したDOMノードの出力のために、Xercesで実装されているパッケージ org.apache.xml.serialize を使いました。
Xercesでは、次の手順で、DOMノードのシリアライズ機能を提供しています。
Document resultDoc = (Document)result.getNode();
org.apache.xml.serialize.OutputFormatで、出力対象のDocumentオブジェクト、文字符号化方法、空白類文字の維持を指定する。
OutputFormat formatter = new OutputFormat(resultDoc, "UTF-8", true);
Writer out = new OutputStreamWriter(new FileOutputStream("DOMresult.xml"), "UTF-8");org.apache.xml.serialize.XMLSerializerで、出力ストリームと出力フォーマットを指定する。
XMLSerializer serializer = new XMLSerializer(out, formatter);
serializer.serialize(resultDoc);
リスト11. DOMによるXSLT処理 (XSLTDOMDemo.java)
import java.io.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.*;
import javax.xml.parsers.*;
import org.w3c.dom.*;
import org.w3c.dom.traversal.*;
import org.apache.xml.serialize.*;
class XSLTDOMDemo {
public static void main(String[] args) {
try {
// DOMパーサ用ファクトリの生成
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
// 名前空間を認識する
factory.setNamespaceAware(true);
// DOM Documentインスタンス用ファクトリの生成
DocumentBuilder builder = factory.newDocumentBuilder();
// 解析とDocumentインスタンスの取得
Document xsltDoc = builder.parse(args[0]);
Document sourceDoc = builder.parse(args[1]);
// XSLTのDOMソース
DOMSource xsltSrc = new DOMSource(xsltDoc);
// ソース・ツリーのDOMソース
DOMSource source = new DOMSource(sourceDoc);
// 結果ツリーのDOMリザルト
DOMResult result = new DOMResult();
// XSLTプロセッサのファクトリの生成
TransformerFactory tFactory = TransformerFactory.newInstance();
// XSLTプロセッサの生成
Transformer transformer = tFactory.newTransformer(xsltSrc);
// 変換と結果ツリーの出力
transformer.transform(source, result);
// 結果DOMツリーの取得
Document resultDoc = (Document)result.getNode();
// 出力フォーマットの設定
OutputFormat formatter = new OutputFormat(resultDoc, "UTF-8", true);
// 出力ストリーム
Writer out = new OutputStreamWriter(new FileOutputStream("DOMresult.xml"), "UTF-8");
// シリアライザの設定
XMLSerializer serializer = new XMLSerializer(out, formatter);
// シリアライズ(直列化)
serializer.serialize(resultDoc);
// 出力ストリームのクローズ
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
リスト11では、一般例を示すために、XMLSerializerを使いましたが、HTML/XSHTML用に、HTMLSerializer/XHTMLSerializerも用意されています。DOM level 3で、シリアライズがサポートされるようになるまでは、これらのクラスを使うのが便利です。
リスト11の実行方法は、リスト3の XSLTDemo.java の場合と同様です。例えば、リスト9のXSLT文書 (XSLTDemo3.xsl) でリスト1のXML文書 (XPathDemo.xml)を変換するには、次のようにコマンドを発行します。結果は、同じディレクトリの "DOMresult.xml" に書き出されます。但し、Document オブジェクト resultDoc からはDTD宣言が欠落しているので、文書型宣言は出力されません。
>javac XSLTDOMDemo.java >java XSLTDOMDemo XSLTDemo3.xsl XPathDemo.xml
SAXによるXSLTの利用は、ストリームやDOMツリーによるAPIとは趣を異にします。SAXのAPIでは、XSLTは、XMLReaderに対するXMLFilterや、ContentHandlerとの連携に威力を発揮します。SAX APIによるXSLTの利用例を、リスト12に挙げます。
リスト12は、XSLTでソースXML文書を変換した結果に、以前作ったコンテント・ハンドラMySAXHandlerを適用するものです。
最初にSAXインタフェースである org.xml.sax.XMLReader を生成します。続いて、後続のコードで利用するデフォルト・ハンドラと javax.xml.transform.sax.SAXTransformerFactory を生成します。SAXTransformerFactory は、TransformerFactory の継承で、SAX用の org.xml.sax.ContentHandler を生成するファクトリ・メソッドを提供します。リスト12では、javax.xml.transform.sax.TemplatesHandler と、javax.xml.transform.sax.TransformerHandler を生成しています。
TemplatesHandler は、XSLT文書を構文解析し、javax.xml.transform.Templates オブジェクトを生成するのに利用します。リスト12では、ErrorHandler などもデフォルト・ハンドラをセットしてから、XSLT文書を構文解析しています。
TransformerHandler は、XML文書を構文解析し、ツリー構造変換するハンドラです。リスト12では、SAXTransformerFactoryのファクトリ・メソッドに、TemplatesHandler がXSLT文書を構文解析して取得した Templates オブジェクトを与えて生成しています。
TranslatesHandler が変換結果を出力する javax.xml.transform.sax.SAXResult は、メソッド setResult() の引数として与えます。SAXResult を生成するに当たり、ターゲットとする ContentHandler を引数に与えることで、TransformerHandler による変換結果が、そのままターゲットの ContentHandler に渡されることになります。
リスト12. SAX用API (XSLTSAXDemo.java)
import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.sax.*;
import javax.xml.transform.stream.*;
import org.xml.sax.*;
import org.xml.sax.helpers.*;
class XSLTSAXDemo {
public static void main(String[] args) {
try {
// SAXパーサのファクトリーの生成
SAXParserFactory factory = SAXParserFactory.newInstance();
// フィーチャーの設定
factory.setNamespaceAware(true);
factory.setFeature("http://apache.org/xml/features/validation/dynamic", true);
factory.setFeature("http://apache.org/xml/features/validation/schema", true);
// SAXパーサの生成
SAXParser parser = factory.newSAXParser();
// XMLReaderの生成
XMLReader reader = parser.getXMLReader();
//デフォルト・ハンドラの生成
DefaultHandler handler = new MySAXHandler();
// ハンドラの登録
reader.setDTDHandler(handler);
reader.setErrorHandler(handler);
// SAXTransformerFactoryの生成
SAXTransformerFactory saxTFactory = (SAXTransformerFactory)TransformerFactory.newInstance();
// TemplatesHandlerの生成
TemplatesHandler templatesHandler = saxTFactory.newTemplatesHandler();
// TemplatesHandlerの登録
reader.setContentHandler(templatesHandler);
// XSLT文書の解析
reader.parse(args[0]);
// Templatesの生成
Templates templates = templatesHandler.getTemplates();
// TransformerHandlerの生成
TransformerHandler transformerHandler = saxTFactory.newTransformerHandler(templates);
// TransformerHandlerの登録
reader.setContentHandler(transformerHandler);
// SAXResultの生成
SAXResult result = new SAXResult(new MySAXHandler());
// SAXResultの登録
transformerHandler.setResult(result);
// 実行
reader.parse(args[1]);
} catch (Exception e) {
e.printStackTrace();
}
}
}
// イベント・ハンドラ
class MySAXHandler extends DefaultHandler {
// ContentHandlerの実装
public void startDocument() throws SAXException {
System.out.println("startDocument()");
}
public void endDocument() throws SAXException {
System.out.println("endDocument()");
}
public void startElement(java.lang.String uri,
java.lang.String localName,
java.lang.String qName,
Attributes atts)
throws SAXException {
System.out.println("startElement()");
System.out.println("\tnamespace=" + uri);
System.out.println("\tlocal name=" + localName);
System.out.println("\tqualified name=" + qName);
for (int i = 0; i < atts.getLength(); i++) {
System.out.println("\tattribute name=" + atts.getLocalName(i));
System.out.println("\tattribute qualified name=" + atts.getQName(i));
System.out.println("\tattribute value=" + atts.getValue(i));
}
}
public void endElement(java.lang.String uri,
java.lang.String localName,
java.lang.String qName)
throws SAXException {
System.out.println("endElement()");
}
public void characters(char[] ch,
int start,
int length)
throws SAXException {
System.out.println("characters()" + new String(ch, start, length));
}
// ErrorHandlerの実装
public void warning(SAXParseException e) {
System.out.println("警告: " + e.getLineNumber() +"行目");
System.out.println(e.getMessage());
}
public void error(SAXParseException e) {
System.out.println("エラー: " + e.getLineNumber() +"行目");
System.out.println(e.getMessage());
}
public void fatalError(SAXParseException e) {
System.out.println("深刻なエラー: " + e.getLineNumber() +"行目");
System.out.println(e.getMessage());
}
}
リスト12の実行結果がリスト13です。XML文書 (XPathDemo.xml) が XSLT文書 (XSLTDemo3.xsl) によって XHTML 文書に変換され、その結果を MySAXHandler が処理していることが分かります。
リスト13. XSLTSAXHandler.javaの実行結果
>javac XSLTSAXDemo.java
>java XSLTSAXDemo XSLTDemo3.xsl XPathDemo.xml
startDocument()
startElement()
namespace=http://www.w3.org/1999/xhtml
local name=html
qualified name=html
attribute name=
attribute qualified name=xmlns
attribute value=http://www.w3.org/1999/xhtml
attribute name=lang
attribute qualified name=xml:lang
attribute value=ja
startElement()
namespace=http://www.w3.org/1999/xhtml
local name=head
qualified name=head
startElement()
namespace=http://www.w3.org/1999/xhtml
local name=meta
qualified name=meta
attribute name=content
attribute qualified name=content
attribute value=text/html; charset=UTF-8
attribute name=http-equiv
attribute qualified name=http-equiv
attribute value=content-type
endElement()
...省略