Sep 12, 2008
フォルダアクションで docbook を PDF に変換する
Mac OS X 上に Docbook 環境を構築してみた。 やりたいのは、フォルダアクションで docbook を PDF 化すること。
docbook 環境のインストール
まずは MacPorts を使用して docbook 関連のライブラリと Apache FOP をインストールする。
$ sudo port install docbook-xml docbook-xsl libxslt fop Password: ---> Fetching xmlcatmgr (略) ---> Installing xmlcatmgr 2.2_1 ---> Activating xmlcatmgr 2.2_1 ---> Cleaning xmlcatmgr ---> Fetching docbook-xml-4.1.2 (略) ---> Installing docbook-xml-4.1.2 4.1.2_1 ---> Activating docbook-xml-4.1.2 4.1.2_1 ---> Cleaning docbook-xml-4.1.2 (略) ---> Installing docbook-xml-4.2 4.2_0 ---> Activating docbook-xml-4.2 4.2_0 ---> Cleaning docbook-xml-4.2 ---> Fetching docbook-xml-4.3 (略) ---> Installing docbook-xml-4.3 4.3_0 ---> Activating docbook-xml-4.3 4.3_0 ---> Cleaning docbook-xml-4.3 ---> Fetching docbook-xml-4.4 (略) ---> Installing docbook-xml-4.4 4.4_0 ---> Activating docbook-xml-4.4 4.4_0 ---> Cleaning docbook-xml-4.4 ---> Fetching docbook-xml-4.5 (略) ---> Installing docbook-xml-4.5 4.5_0 ---> Activating docbook-xml-4.5 4.5_0 ---> Cleaning docbook-xml-4.5 ---> Fetching docbook-xml (略) ---> Installing docbook-xml 4.5_1 ---> Activating docbook-xml 4.5_1 ---> Cleaning docbook-xml ---> Fetching docbook-xsl (略) ---> Installing docbook-xsl 1.72.0_0 ---> Activating docbook-xsl 1.72.0_0 ---> Cleaning docbook-xsl ---> Fetching libxslt (略) ---> Installing libxslt 1.1.22_0 ---> Activating libxslt 1.1.22_0 ---> Cleaning libxslt ---> Fetching fop (略) ---> Installing fop 0.94_0 ---> Activating fop 0.94_0 ---> Cleaning fop $
シングルバイトの docbook ファイルを PDF 化してみる
PDF の Font 周りは面倒なので、とりあえずはシングルバイト文字のみで PDF 化を試してみる。 用意したデータはこんな感じ。
<?xml version="1.0" encoding="UTF-8"?>
<book id="my_test_book">
<title>my test book</title>
<chapter id="chapter1">
<title>Chapter 1</title>
<para>Hello docbook!</para>
</chapter>
<chapter id="chapter2">
<title>Chapter 2</title>
<para>This is single byte docbook document.</para>
</chapter>
</book>
docbook xml → (XSLT) → FO → (Apache FOP) → PDF という様に docbook を PDF に変換する。
何事もなく PDF が生成された。$ /opt/local/bin/xsltproc -o ./test.fo /opt/local/share/xsl/docbook-xsl/fo/docbook.xsl ./test.xml Making portrait pages on USletter paper (8.5inx11in) $ fop -fo ./test.fo -pdf ./test.pdf 2008/09/10 11:45:21 org.apache.fop.hyphenation.Hyphenator getHyphenationTree 致命的: Couldn't find hyphenation pattern en $
マルチバイトの docbook ファイルを PDF 化してみる
次に本命のマルチバイト docbook ファイルの変換に挑戦してみる。 FOP のフォント設定は以下のサイトを参考にさせていただいた。感謝。
- Apache FOP: Fonts
- http://xmlgraphics.apache.org/fop/0.95/fonts.html#basics
- DocBook メモ
- http://cueplot.sourceforge.jp/wiki/index.php?DocBook%20%E3%83%A1%E3%83%A2
<?xml version="1.0" encoding="UTF-8"?>
<book id="my_test_book_ja">
<title>テストブック</title>
<chapter id="chapter1">
<title>第一章</title>
<para>やぁ! Docbook</para>
</chapter>
<chapter id="chapter2">
<title>第二章</title>
<para>日本語は上手く表示できるかな?</para>
</chapter>
</book>
当然駄目だと分かっているが、とりあえずそのまま PDF 化してみる。
手順はシングルバイトのときと全く同様。結果は
やはり Font を設定しなければ化けることが分かったので、仕方なく Font を設定する。 手順は上記のサイトに記載がある通り。
$ cd /opt/local/share/java/fop/0.94/
$ java -cp ./build/fop.jar:./lib/commons-logging-1.0.4.jar:./lib/commons-io-1.3.1.jar org.apache.fop.fonts.apps.TTFReader -d -fn "HiraginoMinchoProW3" "/System/Library/Fonts/\343\203\222\343\203\251\343\202\255\343\202\231\343\203\216\346\230\216\346\234\235 Pro W3.otf" ./hiraginominchoprow3.xml
TTF Reader for Apache FOP 0.94
Parsing font...
Reading /System/Library/Fonts/?q???L??m???? Pro W3.otf...
sfnt version: OpenType with CFF data
(略)
Font Family: Hiragino Mincho Pro
Error while building XML font metrics file.
java.lang.UnsupportedOperationException: OpenType fonts with CFF data are not supported, yet
at org.apache.fop.fonts.apps.TTFReader.loadTTF(TTFReader.java:214)
at org.apache.fop.fonts.apps.TTFReader.main(TTFReader.java:163)
・・・ ヒラギノは現時点の Apache FOP では扱えないらしい。
では、ということで、MS 明朝を試してみた。
MS 明朝は正常に読み込むことができた。$ java -cp ./build/fop.jar:./lib/commons-logging-1.0.4.jar:./lib/commons-io-1.3.1.jar org.apache.fop.fonts.apps.TTFReader -d -fn "MSMINCHO" "./fonts/MSMINCHO.TTF" ./fonts/msmincho.xml TTF Reader for Apache FOP 0.94 Parsing font... Reading /fonts/MSMINCHO.TTF... sfnt version: OpenType 1.0 (略) Font Family: MS Mincho Creating xml font file... Creating CID encoded metrics... Writing xml font file /fonts/msmincho.xml... This font contains no embedding license restrictions. XML font metrics file successfully created. $
後は FOP の設定ファイル fop.xconf を作成するだけ。
<?xml version="1.0"?>
<fop version="1.0">
<renderers>
<renderer mime="application/pdf">
<fonts>
<font metrics-url="/fonts/msmincho.xml" kerning="yes" embed-url="/fonts/MSMINCHO.ttf">
<font-triplet name="MSMINCHO" style="normal" weight="100"/>
<font-triplet name="MSMINCHO" style="normal" weight="200"/>
<font-triplet name="MSMINCHO" style="normal" weight="300"/>
<font-triplet name="MSMINCHO" style="normal" weight="400"/>
<font-triplet name="MSMINCHO" style="normal" weight="500"/>
<font-triplet name="MSMINCHO" style="normal" weight="600"/>
<font-triplet name="MSMINCHO" style="normal" weight="700"/>
<font-triplet name="MSMINCHO" style="normal" weight="800"/>
<font-triplet name="MSMINCHO" style="normal" weight="900"/>
</font>
</fonts>
</renderer>
</renderers>
</fop>
ではマルチバイト docbook の PDF 化に再挑戦。 今回は MS 明朝を使用するので、docbook から FO を作成した後で FO 内の Font 設定を変更する処理を入れる。 docbook → (XSLT) → fo → (sed) → fo → (FOP) → PDF という感じになる。 また、Apache FOP 実行時に上で作成した設定ファイルを指定する必要がある。
マルチバイト docbook の PDF 化に成功!!$ /opt/local/bin/xsltproc -o ./test_ja.fo /opt/local/share/xsl/docbook-xsl/fo/docbook.xsl ./test_ja.xml Making portrait pages on USletter paper (8.5inx11in) $ sed -e "s/font-family=\"/font-family=\"MSMINCHO,/g" ./test_ja.fo > ./test_ja_2.fo $ fop -fo ./test_ja_2.fo -pdf ./test_ja_2.pdf -c ./fop.xconf 2008/09/10 13:14:28 org.apache.fop.hyphenation.Hyphenator getHyphenationTree ?v???I: Couldn't find hyphenation pattern en $
AppleScript で docbook → PDF の変換を行う
docbook の PDF 化に成功したところで、念願の AppleScript での変換を行う。 まずはシェルスクリプトを用意。
#!/bin/sh
DOCBOOK_XML=$1
DOCBOOK_PDF=$2
XSLTPROC=/opt/local/bin/xsltproc
DOCBOOK_XSLT=/opt/local/share/xsl/docbook-xsl/fo/docbook.xsl
FOP=/opt/local/bin/fop
FOP_CONFIG=/fonts/fop.xconf
WORKDIR=`pwd`
WORK_FO=$WORKDIR/tmp.fo
WORK_FO_CONVERTED=$WORKDIR/tmp_converted.fo
echo "Converting docbook -> PDF : $DOCBOOK_XML -> $DOCBOOK_PDF"
if [ ! -f "$DOCBOOK_XML" ];
then
echo "No docbook file found. : $DOCBOOK_XML"
exit;
fi
rm "$WORK_FO" 2> /dev/null
rm "$WORK_FO_CONVERTED" 2> /dev/null
$XSLTPROC -o "$WORK_FO" "$DOCBOOK_XSLT" "$DOCBOOK_XML"
sed -e "s/font-family=\"/font-family=\"MSMINCHO,/g" "$WORK_FO" > "$WORK_FO_CONVERTED"
$FOP -fo "$WORK_FO_CONVERTED" -pdf "$DOCBOOK_PDF" -c "$FOP_CONFIG"
rm "$WORK_FO" 2> /dev/null
rm "$WORK_FO_CONVERTED" 2> /dev/null
次にこのシェルスクリプトを呼び出す AppleScript を用意する。
この AppleScript は "/Library/Scripts/Folder Action Scripts/Image - Duplicate as JPEG.scpt" を参考にさせていただいた(「参考に」と言うより、ほぼそのまま)。
property doneFoldername : "PDF"
property originalsFoldername : "Docbook"
property pdfExtension : "pdf"
property typeList : {"XML"}
property extensionList : {"xml"}
on adding folder items to thisFolder after receiving theseItems
tell application "Finder"
if not (exists folder doneFoldername of thisFolder) then
make new folder at thisFolder with properties {name:doneFoldername}
end if
set the resultsFolder to (folder doneFoldername of thisFolder) as alias
if not (exists folder originalsFoldername of thisFolder) then
make new folder at thisFolder with properties {name:originalsFoldername}
set current view of container window of thisFolder to list view
end if
set the originalsFolder to folder originalsFoldername of thisFolder
end tell
try
repeat with i from 1 to number of items in theseItems
set thisItem to item i of theseItems
set the itemInfo to the info for thisItem
if (alias of the itemInfo is false and the file type of the itemInfo is in the typeList) or (the name extension of the itemInfo is in the extensionList) then
tell application "Finder"
my resolveConflicts(thisItem, originalsFolder, "")
set the newName to my resolveConflicts(thisItem, resultsFolder, pdfExtension)
set the SourceFile to (move thisItem to the originalsFolder with replacing) as alias
end tell
processItem(SourceFile, newName, resultsFolder)
end if
end repeat
on error errorMessage number errorNumber
if the errorNumber is not -128 then
tell application "Finder"
activate
display dialog errorMessage buttons {"Cancel"} default button 1 giving up after 120
end tell
end if
end try
end adding folder items to
on resolveConflicts(thisItem, targetFolder, newExtension)
tell application "Finder"
set the fileName to the name of thisItem
set fileExtension to the name extension of thisItem
if the fileExtension is "" then
set the trimmedName to the fileName
else
set the trimmedName to text 1 thru -((length of fileExtension) + 2) of the fileName
end if
if the newExtension is "" then
set targetName to fileName
set targetExtension to fileExtension
else
set targetExtension to newExtension
set targetName to (the trimmedName & "." & targetExtension) as string
end if
if (exists document file targetName of targetFolder) then
set the nameIncrement to 1
repeat
set the newName to (the trimmedName & "." & (nameIncrement as string) & "." & targetExtension) as string
if not (exists document file newName of the targetFolder) then
set the name of document file targetName of the targetFolder to the newName
exit repeat
else
set the nameIncrement to the nameIncrement + 1
end if
end repeat
end if
end tell
return the targetName
end resolveConflicts
on processItem(SourceFile, newName, resultsFolder)
try
set the targetPath to ((resultsFolder as string) & newName) as string
with timeout of 900 seconds
do shell script "/Scripts/convert-docbook.sh ¥"" & POSIX path of SourceFile & "¥" ¥"" & POSIX path of targetPath & "¥""
end timeout
on error errorMessage
tell application "Finder"
activate
display dialog errorMessage buttons {"Cancel"} default button 1 giving up after 120
end tell
end try
end processItem
この AppleScript をフォルダに関連付けて今回の作業は終了。
TrackBack ping me at
http://www.in-vitro.jp/blog/index.cgi/Apple/20080912_01.trackback
writeback message: Ready to post a comment.
