XMLファイルからPDFファイルを生成する
前回は、Apache FOPを用いてXSL-FO文書を元にPDF文書を生成する方法を紹介した。Apache FOPでは、XSL-FOを直接記述するだけでなく、XML文書からPDF文書を生成する方法も用意されている。具体的には、XML文書をXSLTを利用してXSL-FO文書に変換し、そこからPDFを生成するという形になる。したがってこの方法では、元になるXMLファイルのほかにXSLTを記述したファイルを用意する必要がある。
まずはXMLファイルを用意しよう。本稿では次のような内容を記述した「fop-sample-ja.xml」というファイルを用意した。見てのとおり、<colmun>の子要素として<title>と<abstract>を持つ構造である。
リスト1 fop-sample-ja.xml
<?xml version="1.0" encoding="UTF-8"?>
<colmun>
<title>
攻略! ツール・ド・プログラミング
</title>
<abstract>
この連載ではプログラミングを手助けするツールやライブラリ、フレームワーク、プラットフォームなどについて紹介しています。
</abstract>
</colmun>
これをXSL-FOに変換するXSLTとしては、次のような内容のファイルを「xml2fo-sample.xsl」という名前で作成した。
リスト2 xml2fo-sample.xsl
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/colmun">
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
<fo:layout-master-set>
<fo:simple-page-master master-name="A4-portrait"
page-height="29.7cm" page-width="21.0cm" margin="2cm">
<fo:region-body margin-top="1cm"/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="A4-portrait">
<fo:flow flow-name="xsl-region-body">
<fo:block font-size="14pt" color="red" margin="0.5cm" font-family="IPA Mincho">
<xsl:value-of select="title"/>
</fo:block>
<fo:block font-size="12pt" margin="0.5cm" font-family="IPA Mincho">
<xsl:value-of select="abstract"/>
</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
</xsl:stylesheet>
XSLTに関する詳しい解説は省略するが、テンプレートの基本になっているのは前回の記事のfop-sample-ja.foであり、そこにfop-sample-ja.xmlの<title>要素と<abstract>要素の内容を埋め込む形になっている。すなわち、
リスト3
<xsl:template match="/colmun">
のタグで<colmun>要素にマッチする部分を探し、
リスト4
<fo:block font-size="14pt" color="red" margin="0.5cm" font-family="IPA Mincho">
<xsl:value-of select="title"/>
</fo:block>
<fo:block font-size="12pt" margin="0.5cm" font-family="IPA Mincho">
<xsl:value-of select="abstract"/>
</fo:block>
の部分でその中にある<title>要素と<abstract>要素の値をそれぞれXSL-FO形式のテンプレートに埋め込んでいる。
PDFファイルの生成は、XSL-FOファイルの場合と同様にfopコマンドで行うことができる。次のように-xmlオプションでXMLファイルを、-xslオプションでXSTLファイルを指定すればよい。また、日本語フォントを使用しているので-cオプションによる設定ファイルの指定も必要となる。
プロンプト1
>fop -c conf/fop.xconf -xml fop-sample-ja.xml -xsl xml2fo-sample.xsl pdf-from-xml.pdf
コマンドが成功すれば、「pdf-from-xml.pdf」というPDFファイルが生成される。内容は図1のようになる。
ちなみに、PDFファイルを直接生成するだけでなく、XSL-FOファイルを生成することもできる。その場合は、出力先のファイル名を次のように-fooutオプションで指定すればよい。
プロンプト2
>fop -c conf/fop.xconf -xml fop-sample-ja.xml -xsl xml2fo-sample.xsl -foout fo-from-xml.fo
JavaプログラムからApache FOPを利用する
次に、JavaプログラムからApache FOPを利用してみよう。まずはXSL-FOファイルからPDFファイルを生成するプログラムを作ってみる。JavaプログラムでApache FOPを利用するには、buildフォルダにあるfop.jarと、libフォルダにある各種jarファイルをクラスパスに含めてコンパイル/実行を行う必要がある。特に、XSLの扱いにはJAXP APIを利用するためxml-apis-xxxx.jarは必須となる。
以下に、fop-sample-ja.fo(前回使ったXSL-FOファイル)を読み込み、fop-sample-ja.pdfを出力するプログラムの例を示す。 インポートしているクラスのうち、javax.xml.transformおよびorg.xml.saxパッケージのものはJAXP APIに含まれるクラスで、org.apache.fop.appsパッケージのものはApache FOPで提供されるクラスである。
リスト4
import java.io.*;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.sax.SAXResult;
import javax.xml.transform.stream.StreamSource;
import org.xml.sax.SAXException;
import org.apache.fop.apps.FOPException;
import org.apache.fop.apps.Fop;
import org.apache.fop.apps.FopFactory;
import org.apache.fop.apps.MimeConstants;
public class Fo2PdfSample {
public static void main(String[] args) {
// FopFactoryオブジェクトの取得
FopFactory fopFactory = FopFactory.newInstance();
try {
// 日本語フォントの設定の追加
fopFactory.setUserConfig("[PATH_TO_FOP]/conf/fop.xconf");
// 出力先の指定
OutputStream output = new BufferedOutputStream(new FileOutputStream("fop-sample-ja.pdf"));
// 出力フォーマットを指定してFopオブジェクトを生成
Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, output);
// XSL-FOファイルの指定
Source source = new StreamSource("fop-sample-ja.fo");
// 変換用オブジェクトの生成
TransformerFactory factory = TransformerFactory.newInstance();
Transformer transformer = factory.newTransformer();
// 結果格納用のResultオブジェクトを生成
Result result = new SAXResult(fop.getDefaultHandler());
// 変換を実行
transformer.transform(source, result);
output.close();
} catch (FOPException ex) {
ex.printStackTrace();
} catch (SAXException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
} catch (TransformerConfigurationException ex) {
ex.printStackTrace();
} catch (TransformerException ex) {
ex.printStackTrace();
}
}
}
PDFの生成を行うのに重要なのはFopクラスだが、FopオブジェクトはFopFactoryオブジェクトから生成する。日本語フォントを使う場合などは、setUserConfigメソッドを使ってFopFactoryに設定ファイルを指定しておく。Fopオブジェクトの生成はnewFopメソッドで行える。このメソッドの引数には、出力フォーマット(MIMEタイプ)と出力先のストリームオブジェクトを指定する。出力フォーマットの指定にはMimeConstantsクラスが利用できる。
元になるXSL-FOファイルはSourceオブジェクトとして読み込む。今回はファイルストリームから読み込むためにStreamSourceを使っている。実際のPDFの出力にはTransformerクラスに用意されたをtransformメソッドを使用する。このメソッドはXML関連のファイルのフォーマット変換を行うためのもので、第1引数にSourceオブジェクトを、第2引数に結果を格納するためのResultオブジェクトを渡して実行する。
本稿の例では、Resultオブジェクトをfop.getDefaultHandlerメソッドの結果を元にして作成している。これによって、Resultに渡された結果がFopオブジェクトのハンドラで処理され、PDFファイルとして出力されるようになる。
このプログラムをコンパイル/実行すると、fop-sample-ja.pdfというPDFファイルが出力される。内容は図1に示したものと同様になる。