XSLT の API

revised: Nov./16th/2003

DOM APIによるXSLTの利用

JAXPでは、XSLTを処理するために、ストリーム、DOM、SAX用の三つのパッケージと、これらに共通する上位のパッケージを提供しています。

リスト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の場合は、DOMSourceDOMResult を使って、DOMツリーである Document オブジェクトに入出力します。ストリームとDOMでは、入出力対象がデバイスかDOMツリーであるかの相違しかありません。SAXの場合も、SAXSourceSAXResult により入出力を制御できますが、イベント駆動型であるために、ハンドラによる処理が必要になり、ストリームやDOMに比べると、やや複雑です。

リスト11は、DOMベースのXSLT処理用のコードです。この例では、最初にXSLTとソースXMLの2つのDocumentオブジェクトでつくり、これを引数にして、DOMSourceオブジェクトxslSrcsourceを生成しています。DOMResultオブジェクトresultは、最初は空っぽで生成しています。続いて、XSLTプロセッサtransformerをファクトリtFactoryから生成し、メソッドtranform()で実際に変換が行われるとresultに結果ツリーが書き込まれます。

リスト11の後半は、DOMツリーの出力用のコードです。DOM level 1, level 2では、シリアライズのAPIは提供されていません。ここでは、DOMResultから取り出したDOMノードの出力のために、Xercesで実装されているパッケージ org.apache.xml.serialize を使いました。

Xercesでは、次の手順で、DOMノードのシリアライズ機能を提供しています。

  1. DOMResultからNodeを取り出す。リスト11では、DocumentオブジェクトresultDocになる。
    Document resultDoc = (Document)result.getNode();
  2. org.apache.xml.serialize.OutputFormatで、出力対象のDocumentオブジェクト、文字符号化方法、空白類文字の維持を指定する。
    OutputFormat formatter = new OutputFormat(resultDoc, "UTF-8", true);
  3. 出力ファイルのストリームを生成する。リスト13では、バッファリングのストリームでラップしている。
    Writer out = new OutputStreamWriter(new FileOutputStream("DOMresult.xml"), "UTF-8");
  4. DOMノードを出力するためのorg.apache.xml.serialize.XMLSerializerで、出力ストリームと出力フォーマットを指定する。
    XMLSerializer serializer = new XMLSerializer(out, formatter);
  5. シリアライズ(直列化)を行い、実際に出力ストリームへ書き出す。
    serializer.serialize(resultDoc);
  6. リスト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の実行方法は、リスト3XSLTDemo.java の場合と同様です。例えば、リスト9のXSLT文書 (XSLTDemo3.xsl) でリスト1のXML文書 (XPathDemo.xml)を変換するには、次のようにコマンドを発行します。結果は、同じディレクトリの "DOMresult.xml" に書き出されます。但し、Document オブジェクト resultDoc からはDTD宣言が欠落しているので、文書型宣言は出力されません。

    >javac XSLTDOMDemo.java
    >java XSLTDOMDemo  XSLTDemo3.xsl XPathDemo.xml
    

    SAX APIによるXSLTの利用

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


    Copyright © 2003 SUGAI, Manabu. All Rights Reserved.