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() ...省略