翻訳ものを JF 互換のフォーマットで管理しよう、かな? と思って XML の仲間である DocBook について調べてみた。自分の主な目的は emacs で DocBook フォーマットのソース文書を書き、 HTML ページへ変換すること。内容は上っ面だけの「おいしいとこ取り」なので、 SGML とは何か、 DSSSL スタイルシートとは何か、など理論の話は、必要であれば上記のリンクなどで調べていただきたい。
ドキュメントソースファイル (SGML) の編集や各種フォーマット (HTML や PDF) への変換に必要なものは JFプロジェクト の SGML Tips for JF にある通り。 Fedora Core 4 の場合の手順を要約しておく。 Windows上で同様の環境を作りたい人は、次ページの Cygwin+Meadow環境でのDocBook のほうを読んでいただくといいだろう。
emacs を使うのだが、 psgml というプラグインみたいなもの (非常に強力!) の能力を活用する。書き始め方の手順は以下。最近は UTF-8 も一般的になってきたようだが、文字コードは互換性を重視して EUC-JP を使う。
emacs は気が狂うほど多機能で複雑。とにかくすぐ使いたい人には Tomoya Sakurai さんの「Emacs 簡易コマンドリファレンス」のような要点だけのページが一番役に立つかもしれない。
下に、キーシーケンスの最低限のものだけ挙げておく。読み方は、例えば C-x 1 は、 Ctrl+x を打ってから 1 のキーを押すことを表し、 M-x は Alt+x を打つことを意味する。なぜ Alt なのに A でなく M なのかというと (まあ非常に乱暴な表現なのは承知の上で) UNIX では Alt キーを「メタ」キーと呼ぶから。コツとしては、例えば C-x C-f の場合なら、実質的には Ctrl キーを押し下げたまま エックスエフッ! と打てばいい。なお、 Ctrl+Alt+x のように 3 つのキーを組み合わせる時、一般的には C-M-x と表記するが、ここでは、直感的に見やすいと思い CM-x のように表すことにした。
補足をひとつ。テキスト範囲を選択するには、マウスでドラッグしてもできるし、始点位置で C-@ してから終点位置にカーソルを移動すれば (設定を変えないと目には見えないが) その間が選択範囲となる。
ファイルを開く | C-x C-f | バッファを指定してアクティブなウィンドウに表示 | C-x b | |
ファイルを開く (他のウィンドウへ) | C-x 4 f | バッファ一覧 (中クリックで選択できる) | C-x C-b | |
ファイルを保存 | C-x C-s | アクティブでないウィンドウに ..同上 | C-x 4 b | |
名前を付けて保存 | C-x C-w | マーク (カーソル位置を範囲選択の始点にする) | C-@ | |
emacsを終了 | C-x C-c | 選択範囲をカット | C-w | |
コマンドを中止 | C-g | 選択範囲をコピー | M-w | |
アクティブなウィンドウ以外閉じる (バッファは残る) | C-x 1 | カーソル位置から行末までをカット(キルと呼ぶ) | C-k | |
アクティブなウィンドウを閉じる (バッファは残る) | C-x 0 | カーソル行全体をキル(本当は複合ワザ) | C-a C-k C-k | |
別のウィンドウに移る | C-x o | ペースト(ヤンクと呼ぶ)(マウスの中クリックでも可) | C-y | |
任意のバッファをメモリ上から削除 | C-x k | 文頭へジャンプ (Ctrl+Shift+,) | M-< | |
アンドゥ (右記は Ctrl+Shift+\ を意味する) | C-_ | 文末へジャンプ (Ctrl+Shift+.) | M-> |
C-x C-f <ファイル名をタイプ>
M-x <sgml-mode とタイプ>
C-x [Ret] f <euc-jp-unix とタイプ>
<?xml version="1.0" encoding="EUC-JP"?> <!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook V4.2//EN">なぜかバージョン 4.3 や 4.4 の DTD を指定するとエラーになってダメだ。 XML で書く場合は system identifier が必要なので下記のようになる。もちろん docbookx.dtd のパスはディストリビューションやシステム構成よって違うので確認が必要。
<?xml version="1.0" encoding="EUC-JP"?> <!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook V4.2//EN" "/usr/share/sgml/docbook/xml-dtd-4.2-1.0-26/docbookx.dtd">なお、いちいちこれらを書くのは面倒なので、 emacs psgml をカスタマイズ しておく。
C-c C-p
<!-- -*- sgml -*- -->を書いておけばいい。
SGMLモードになると、 emacs のメニューバーの項目が変わる。特に Markup メニューの項目は非常に使える。以下は、ほとんどだが全部ではない。キーボードだけでやれという超emacs達人もいらっしゃるだろうが、SGMLタグに関しては、マウスを併用した方が効率がいいかもしれない。
なお、メニューによる命令とキーコマンドの他に、ここでは取り上げないが、 M-x sgml-... のようにコマンドを直接打つ方法もある。 psgml に限って言えば、 `sgml-' の後に打つべきコマンドはメニューコマンド名を `-' でつないだものであることが多い。例を挙げると、メニューコマンド Insert Element をコマンドで実行するには M-x sgml-insert-element [RET] とタイプすればいい。また、ミニバッファコマンドに共通の話だが、 `sgml-in' のように途中まで打って Tab キーを叩くと、 emacs が続きを補完してくれる。
メニューが変わらなかったり以下のキーが効かない時は、psgml パッケージがインストールされていないことを疑うべし。
Markup メニュー
メニューコマンド | キーコマンド | 用法 |
Insert Element | C-c C-e | カーソル位置にタグ (開始終了の組) を挿入。 |
Insert Start-Tag | C-c < | カーソル位置にタグ (開始タグのみ) を挿入。 |
Insert End-Tag | カーソル位置にタグ (終了タグのみ) を挿入。 | |
End Current-Tag | C-c / | カーソル位置が属する一番内側のエレメントをそこで閉じる。 |
Tag Region | C-c C-r | 選択した範囲をタグで囲む。 |
Insert Attribute | C-c + | カーソル位置が属するタグに属性を追加。 |
Add Element to Element | C-c Tab | カーソル位置が属するエレメント内に新たなタグ (開始終了組) を挿入。 |
Modify メニュー
メニューコマンド | キーコマンド | 用法 |
Normalize | ドキュメント全体についてタグや属性の間違いを検査・自動修正。終了タグの抜け、属性の`='抜けなど。 | |
Normalize Element | カーソル位置の一番内側のタグの間違いを自動修正。 | |
Make Character Reference | C-c # | カーソル位置にある 1 文字をエンコードする。例えば `<' なら `<' へ。 |
Unmake Character Reference | 上記の反対。カーソルは対象コードの `&' に位置していなければならない。 | |
Change Element Name | C-c = | カーソルに一番近い位置のタグを別のタグに変更。開始・終了タグがセットで変わる。 |
Edit Attributes | C-c C-a | カーソル位置が属するタグの属性を編集。そのタグの持てる属性の一覧が別ウィンドウに表示され、値の変更や追加が可能。項目間は Tab で移動、設定済みの属性を解除する (#DEFAULT に戻す) には C-c C-d。編集が終わったら C-c C-c で完了、反映せずに中断するには C-x 0。 |
Kill Element | CM-k | カーソル位置の開始タグから終了タグまでを子タグやテキストごと消去。カーソルは開始タグの `<' になくてはならない。 |
Kill Markup | C-c C-k | カーソル位置のタグを削除。そのタグ単体で、内容や終了 (/開始) タグはタッチされない。カーソルは `<' になくてはならない。 |
Untag Element | C-c - | カーソル位置のタグを開始・終了タグとも削除し、中のテキストや子タグは残す。カーソルがテキスト上にある場合には、そのすぐ外側を囲むタグが削除対象となる。 |
Move メニュー
メニューコマンド | キーコマンド | 用法 |
Beginning of Element | CM-e | カーソル位置のエレメント (テキスト上にある時はすぐ外側のタグ) の終了タグへジャンプ。 |
Insert Start-Tag | CM-a | カーソル位置のエレメント (テキスト上にある時はすぐ外側のタグ) の開始タグへジャンプ。 |
Forward Element | CM-f | 次のタグへジャンプ。移動範囲はカーソルのあった位置を囲むすぐ外側のエレメント内だけで、その中で同じ階層に並列するエレメントへ順次移動。 |
Backward Element | CM-b | 前のタグへジャンプ。 Forward Element の逆方向。 |
Backward Up Element | CM-u | ひとつ親のエレメントの開始タグへジャンプ。 |
Down Element | C-c C-n | ひとつ親のエレメントの終了タグへジャンプ。 |
Next Data Field | C-c C-d | テキストデータを持つ (持てる) エレメントへ順次ジャンプ。例えば、次の <para> へは飛ぶが、エレメントの外箱にしかなれない <section> タグは飛び越される。階層には左右されない。 |
Next Trouble Spot | C-c C-o | タグにエラーのある箇所を探してジャンプ。 |
メニューコマンド | キーコマンド | 用法 |
What Element | C-c C-w | カーソル位置の属するタグ階層構造を emacs のエコー行に表示する。 |
Show Context | C-c C-c | ほぼ上と同じだが、SGMLエレメントだけでなく DOCTYPE 定義なども含めた階層。 |
Validate | C-c C-v | ドキュメントに指定してある DTD と照合して構造的エラーをチェックする。内部的には、 psgml モジュールが外部コマンド `nsgmls -s file ' を実行する仕組み。ただし、現行の SGMLモードでは emacs をカスタマイズしないと、 SGML DocBook の検証はできるても XML DocBook は検証できない。ダメな場合は nsgmls (または onsgmls) を直接使って検証しなければならない。 |
DTD メニュー
メニューコマンド | キーコマンド | 用法 |
Parse DTD | C-c C-p | ドキュメントに指定してある DTD を読み込む (読み込み直す)。 |
Info > Describe Element Type |
ミニバッファにタイプしたタグについて DTD から情報を表示。 | |
Info > List Elements |
DTD に定義されているエレメント (タグ) を全てリストアップ。 |
その他
メニューコマンド | キーコマンド | 用法 |
- | C-c C-h | psgml コマンドのヘルプ。 |
- | C-h v | 指定の emacs環境変数の今現在の設定値を表示 (psgml に限った機能ではない) |
いつも使うユーザの ~/.emacs ファイルに psgml 用の定義 (LISP命令) を書いておけば、 psgml の設定を或る程度カスタマイズできる。 Fedora Core 4 で試したところ、ファイルタイプとの関連付け項目は必要なかったが、一部デフォルト設定の変更と、カスタムメニューを作ることにした。 .emacs ファイルへの追加コードは以下。 Markus Hoenicka の SGML for Windows NT を大いに参考にした。コピーペーストに使いやすい、連番なしの単独ファイルはここ。
1: ;; define xml mode 2: (or (assoc "\\.xml$" auto-mode-alist) 3: (setq auto-mode-alist (cons '("\\.xml$" . sgml-xml-mode) 4: auto-mode-alist))) 5: 6: (defun sgml-xml-mode () 7: "This version of xml mode is just a wrapper around sgml mode." 8: (interactive) 9: (sgml-mode) 10: (make-local-variable 'sgml-declaration) 11: (make-local-variable 'sgml-default-doctype-name) 12: (setq 13: sgml-default-doctype-name "xml" 14: sgml-declaration "-wxml /usr/share/sgml/xml.dcl" 15: 16: sgml-always-quote-attributes t 17: sgml-minimize-attributes nil 18: sgml-omittag t 19: sgml-shorttag t 20: ) 21: ) 22: ;; sgml-mode default variables 23: (setq 24: sgml-auto-activate-dtd t 25: sgml-auto-insert-required-elements t 26: sgml-balanced-tag-edit t 27: sgml-indent-data nil 28: sgml-indent-step nil 29: sgml-insert-missing-element-comment nil 30: sgml-live-element-indicator nil 31: ;sgml-validate-command "onsgmls -s %s %s" 32: sgml-custom-markup '( 33: ("Insert DocType (SGML V4.2)" "<?xml version=\"1.0\" encoding=\"EUC-JP\"?> 34: <!DOCTYPE article PUBLIC \"-//OASIS//DTD DocBook V4.2//EN\">\n\r") 35: ("Insert DocType (XML V4.2)" "<?xml version=\"1.0\" encoding=\"EUC-JP\"?> 36: <!DOCTYPE article PUBLIC \"-//OASIS//DTD DocBook XML V4.2//EN\" 37: \"/usr/share/sgml/docbook/xml-dtd-4.2-1.0-26/docbookx.dtd\">\n\r") 38: ) 39: )
<説明>
\"/usr/share/sgml/docbook/xml-dtd-4.2-1.0-26/docbookx.dtd\">\n\r")
を、あなたの環境で使用する XML DTD に合わせて書き換えておく必要がある。なお、 sgml-* で始まる変数の値を決める際、デフォルトあるいは現在どのような値が設定されているのかが分かると参考になることがある。それには emacs のキーコマンド C-h v が役に立つ。
ついでの雑多な .emacs 設定 (sgml とは関係ない。 For Emacs21 on Fedora Core 4/5)。この部分の単独ファイルはここ。 |
|
SGML DocBook なら emacs上で確実に validate できる (前述「入力の仕方」の「SGMLメニュー」参照)。しかし、 XML DocBook を検証したい場合には、現行の psgml モジュールの問題で、 nsgmls または onsgmls (nsgmlsは、 Fedora Core 4 では openjade パッケージの一部で、実は nsgmls へのシンボリックリンク) を直接使わなくてはならないかもしれない (.emacs ファイルのカスタマイズで解決可能)。 3 番目の引数は後述の XML Docbook -> HTML変換で触れている XML エンティティのデクラレーションファイル名。
user$ nsgmls -s -wxml /usr/share/sgml/xml.dcl targetfile.xml
検証の際、 "xml.dcl:1:W: SGML declaration was not implied" (「SGMLデクラレーションは明示的に宣言してはならない」) という警告が必ず出るが、これは無視しても問題なく、構造の検証自体は正常に行われる。
コンバートには、元の XMLタグと出力メディア上でのフォーマットとを対応づけるスタイルシートが必要となる。大元のスタイルシートそのものは既に述べた「必要なツールの準備」でインストール済みだが、パラメータの調整と媒介としての機能を持つ作業用の DSLスタイルシートがもうひとつ必要だ。一番手っ取り早いのは、JFプロジェクトのスタイルシートをダウンロードして雛形に使わせてもらうことだろう。
まず、 DSLスタイルシートの置き場所を作る。置き場所は何処でも構わない (例えば自分のホームディレクトリ下)。ただし、下記のようなプライベートでないディレクトリを使う場合には、一般ユーザで作業する利便性のためにスティッキービットを立てておくと便利だ。当メモでは、このパスを前提に以後の説明を進めていくことにする。
root# mkdir /usr/local/share/sgml/stylesheets/ root# chmod -R 1777 /usr/local/share/sgml
http://www.linux.or.jp/JF/workshop/archives/jf-custom.dsl を上記 /usr/local/share/sgml/stylesheets/ へダウンロードする。 Tips for JF で指示されているような調整は RedHat系では必要ないが、実際のコンバートがうまくいかない場合は、元の <!ENTITY... をコメントアウトして;
<!ENTITY docbook.dsl SYSTEM "/usr/share/sgml/docbook/dsssl-stylesheets/html/docbook.dsl" CDATA dsssl>
を入れる。 dsssl-stylesheets/ は実際には dsssl-stylesheets-x.x/ へのシンボリックリンクだ。
カスタマイズの仕方は後述する。まずはそのままで実際に変換して、結果を見てみてからいじったほうがいいだろう。
openjade を使用する。オプションの意味は;
もうひとつ、openjadeパッケージには、openjade などのラッパーとして働くシェルスクリプトで jw (Jade-Wrapper) というものが付属しており、そちらを使う手もある。
user$ cd /what/dir/to/output user$ openjade -t sgml-raw -i html \ -d /usr/local/share/sgml/stylesheets/jf-custom.dsl /input/file.sgml
user$ openjade -t sgml-raw -i html -V nochunks \
-d /usr/local/share/sgml/stylesheets/jf-custom.dsl /input/file.sgml \
> /what/dir/outputfile.html
しかしいちいちこんなコマンドを発行するのは面倒だ。そこでよく行われるのが、Makefile を用意する方法。例として、Makefileのサンプルを置いておく。その中では、セクション毎に分割されたファイルへの変換には jw のほうを使っている。
サンプルMakefile の使用法:
あらかた SGML からの場合と同じ。ただし、インプットファイルの手前に XMLエンティティ を定義する宣言ファイル (declaration) を指定する必要がある。 そうしないと "X20AC is not a function name" のようなエラーメッセージが山ほど出てコンバートできない (LDP Author Guide の中でも触れられている FAQ のひとつ)。 Fedora Core 4 上での調査では、デクラレーションファイルの選択肢はふたつあり、ひとつはパッケージ sgml-common によってインストールされる /usr/share/sgml/xml.dcl、もうひとつは openjade によって入る /usr/share/sgml/openjade-x.x.x/OpenSP/xml.dcl。
user$ openjade -t sgml-raw -i html \
-d /usr/local/share/sgml/stylesheets/jf-custom.dsl \
/usr/share/sgml/xml.dcl /input/file.xml
OpenJade のマニュアルをほじくり返しても見つからず、実験によって分かったことだが、 openjade に以下のような引数を与えることによって、 HTML でなく CSSファイルを出力させることができた;
openjade -t html -i html -d /path/to/jf-custom.dsl -o output.css /input/file.sgml
ただし、これで出力された CSS は非常にイイカゲンなもので、実用はできない。しかし、少なくとも、本来 DSSSL スタイルシートが持つ数百に上るクラスや ID の中から、実際にそのドキュメントの中で使われているものだけが網羅されるので、自分で CSS を作成する時の参考になる。
変換の際の仕上がりは DSSSL スタイルシート が握っているわけだが、通常、大元の DSSSL はいじらない。そもそも調整のためにある DSL ファイルをカスタマイズする。このページでの説明の流れで言えば、「実作業用DSLスタイルシートの用意」で準備した jf-custom.dsl をいじることになる。
なお、グローバルなパラメータ調整は、じつはメインの DSSSL スタイルシートに付属する一種の設定ファイル、 dbparam.dsl (Fedora の場合 /usr/share/sgml/docbook/dsssl-stylesheets/html/ 下) で行われており、実作業用DSLスタイルシート (jf-custom.dsl) は各項目をオーバーライドする形で働く。 dbparam.dsl には膨大な数のパラメータが書かれているので、下記に紹介している以外の設定がほしくなったら 、そこから必要な項目を実作業用DSLへコピーして使うといい。
吐き出される HTML のヘッダに CSS スタイルシートための <LINK REL=...> を入れたいと思うかもしれない。jf-custom.dsl の場合なら、
(define %html-pubid% ...) の下あたりに
(define %stylesheet% "name_of_your_stylesheet.css")
と 1 行足せばいい。
常識的に考えて、現行の jf-custom.dsl はひとつ間違いを犯していて、このスタイルシートを使って吐き出したページには charset が明示されないので、世の中にたくさんの文字化けドキュメントを生み出す原因になっている。きちんと META タグを付けさせるには jf-custom.dsl に;
(define %html-header-tags% '( ("META" ("NAME" "Content-Type") ("CONTENT" "text/html; charset=EUC-JP")) ))
を書き加える。真ん中の行だけを同じ要領で増やせば他の META タグを追加することも可能だ。
チャプター:
(define %chapter-autolabel% #f)
セクション:
(define %section-autolabel% #f)
この例の場合 3階層目まで目次にリストされる。
(define (toc-depth nd) 3)
jf-custom.dsl のデフォルトでは <body bgcolor="xxxxxx" text="xxxxxx"> といった具合に body タグに配色定義が付加される。外部 CSS などによってスタイルを定義する場合には、邪魔になるのでこの設定を切る。要は %body-attr% リストをカラにすればいい。
(define %body-attr% (list) )
jf-custom.dsl は、デフォルトではテーブルの上下を <hr> で修飾するようになっている。これをやめさせるには、下記の定義をこのようにコメントアウト、または #t (true) を #f (false) に変える。
;;(define %table-rules% #t)
DocBook ではアンカーへのリンクを作成するには <link> を使うが、ファイル単位や外部へのリンクを作成する時には <ulink> を使う。この定義はおそらく jf 独自のものだが、 jf-custom.dsl にある以下の部分を変更することで、 <ulink> から作成される <a href..> HTMLタグには target="_blank" を付けさせることができる。 jf のデフォルトでは "_TOP" になっている。
(element ulink
(make element gi: "A"
attributes: (list
(list "HREF" (attribute-string (normalize "url")))
(list "TARGET" "_blank"))