| 1. プログラムリスト
もっともわかりやすいと思うので、「SARI関連」ページをとりあげます。テキストエディタSARIのアドインプログラム類を公開しているページです。
2. 対応する文法
(このハウツー執筆時点のものを使います。時間がたつとデザインや内容を変更しているかもしれません。あらかじめご了承ください。) ページタイトルを書いたヘッダ部と、著作権などを表示したフッタ部を除外すると、このページは、プログラムの一覧を表形式で表示したものと、それらのプログラムの詳しい説明部分からなりたっています。 この表形式の部分と詳細説明の部分は同じXMLデータから生成しており、そのXMLデータは、KELFの下記文書からエキスポート生成したものです。 addinfiles.txtをご覧いただけば想像していただけるように、この文書は、文法のタイトルパターンとして、
3. 埋め込み属性
^!0-(.+)$ を設定し、「タイトルの種類で階層構造を作る」をチェックして作成したものです。(!1から!6で、\s*を入れて行頭空白を許容しているのは、階層によるインデントを意図したものです。しかし実際は使っていません。)^\s*!1-(.+)$ ^\s*!2-(.+)$ ^\s*!3-(.+)$ ^\s*!4-(.+)$ ^\s*!5-(.+)$ ^\s*!6-(.+)$ 上と同じパターンを強調単語に指定すると構造が見やすくなるでしょう。 文書構造の概観をXML風に書けば、次のようになります。 <program> 上の<program>要素のひとつが、ひとつのプログラムに対応します。文書内にはいくつかの<program>要素が並列に存在します。<name/> <filename/> <size/> <version/> <date/> <author/> <type/> <marker/> <abstract/> <explanation/> <link> <url/> <text/> </link> <map> <name/> <area> <shape/> <coords/> <href/> <alt/> </area> </map> <image> <src/> <alt/> </image> </program> <program>要素の下部要素<explanation>は、そのプログラムについての詳しい説明です。改行を生かしたいので、この要素については、エクスポート時に、「基本的な設定」ページで「段落をタグで囲む」をチェックして、段落を<p>で囲むようにします。 <abstract>は一行説明です。表形式の表示でこの部分を使います。一行ですので段落を囲む必要はありません。 プログラムに画像がある場合はイメージファイルを関連づけます。<image>要素です。 ただ、画像をそのまま表示すると、ダイアルアップ接続の場合、ページ表示に時間がかかりすぎる恐れがあります。そのため、別に小さな画像を用意しておき、その画像をクリックすれば、プログラムの画像を表示するようにしています。javascriptを使います。そのトリガーにするのが<map>要素です。 <marker>要素は、アンカーのnameかidとして利用するためです。 他はだいたい要素名から想像していただけるでしょう。 addinfiles.txt中、ところどころに、
4. XMLファイルを作成
~xattr; ではじまる行があります。埋め込み属性です。 一定の形式で記入しておくことにより、エクスポート時に、自動的に属性を設定します。属性行と認識した場合、その行は本文から除去してエクスポートします。 KELFのヘルプには書いてありますが、再述すると、 (行頭)接頭辞 + 属性名 + 「=」 + 値(行末) という形式です。この文書の場合、接頭辞は~xattr;です。 また、この文書では、ほとんどの属性をCDATA #IMPLIEDで扱っていますので、使用していませんが、属性定義を文書中に埋め込んでおくことも可能です。その形式は、上とまったく同じで、デフォルト接頭辞は~xattrdef;です。 これらの埋め込み属性を有効にするには、エクスポート時に、「その他の要素名や属性名の設定」ページで、「文書中の埋め込み属性を検索する」をチェックしなければなりません。 addinfiles.txtでは、主に画像の配置などを埋め込み属性を使って決めています。 もちろん、XSL作成段階で、画像の配置などは任意に決定できるわけですが。 エクスポート機能で、
5. XSL言語の構造
addinfiles.txt ⇒ addinfiles.xml を作成します。 ウィザードの最初のページで、「セクションタイトルを要素名にする」と「一部分を抽出して要素名にする」をチェックしておきます。この場合、抽出用の正規表現は^!\d+-(.+)$で、マッチさせる部分は1です。 「その他の要素名や属性名の設定」ページで、「文書中の埋め込み属性を検索する」をチェックするのも忘れずに。 なを最後のページで、「不要なデフォルトid属性を出力しない」をチェックしておくと、セクションに対して付加されるデフォルトid属性の出力が抑制できます。このオプションは、セクション間リンクを作る設定がどこかにひとつでも存在すると、選択できません。 これでデータのXMLは作成できたわけです。 これをブラウザ上でどう表現するかです。 ブラウザで表示するためにはXSLを書かなければなりません。 XSLについて解説するのは筆者の任ではありません。ただ、まったく書かないのも不親切と思いますので、XSLを知らない人のためのとっかかりだけを書きます。XSLをご存知の方はこれ以降を読んでいただく必要はありません。
6. ページの組み立て
XSLそれ自体がXMLです。 すなわち、開始タグ<xxx>と終了タグ</xxx>が明確な入れ子構造になっていなければなりません。<xxx>なにか</xxxx>という形です。中身がないときは<xxx/>と省略できます。 既存のXSLファイルをエディタで見てください。ちょうど、例2でエクスポート出力したkelffaq.xslがあるので、これを使いましょう。 ファイル全体が <?xml version="1.0" encoding='UTF-8' ?> <xsl:stylesheet version="1.0" .....> さまざまな記述 </xsl:stylesheet> という構造になっているのがわかるでしょう。<xsl:stylesheet>〜</xsl:stylesheet>がもっとも外側の要素です。この部分はそのまま使ってください。 次にどういう形で出力するかを規定します。それが、 <xsl:output method='html' encoding='UTF-8' doctype-public='-/W3C//DTD HTML 3.2 Final//EN'/> という部分です。 この要素は中身がないので、<xxxx/>という省略形を使っています。 意味としては、HTMLファイルを出力すること、その文字コードはUTF-8であることを宣言しています。 これもこのまま使います。(htmlの文書型定義でバージョンを4.0にして、doctype-public='-/W3C//DTD HTML 4.0 Final//EN'/でもいいです。) その次、 <xsl:template match='/'> さまざまな記述 </xsl:template> という構造があります。 ここがメインです。 <xsl:template>〜</xsl:template>はXSLで使う処理の単位だと考えてください。match='/'という記述により、この処理の単位には、変換元のXMLデータ中、もっとも外側にある要素がノード化されて流れ込むことになります。kelffaq.xmlならkelffaqDoc、 上のaddinfiles.xmlならaddinfilesDocです。 だからkelffaq.xmlに対して、 <xsl:template match='/'> <xsl:apply-templates select='kelffaqDoc' /> </xsl:template> <xsl:template match='kelffaqDoc'> kelffaqDocに対する何かの処理 </xsl:template> と書くと、kelffaqDocp要素を処理できます。 上の<xsl:apply-templates select=....>は、流れ込んだノードのうちkelffaqDocに合致するものを扱えという命令です。<xsl:template match='temp'></xsl:template>という処理単位があり、これはkelffaqDocにマッチするものを処理する単位ですので、この処理単位が呼ばれます。 基本的に、XSLは、この<xsl:apply-templates select='...'>と、それに対応する<xsl:template match='...'>をうまく組み合わせることにより全体を処理するわけです。 kelffaq.xslに戻り<xsl:template match='/'></xsl:template>の中を見ると、 <xsl:template match="/"> <html> <head> <title>kelffaqDoc</title> </head> <body・・・> <xsl:apply-templates select="//doctitle"/> <xsl:apply-templates select="//contents"/> <xsl:apply-templates select="//rank0"/> </body> </html> </xsl:template> となっています。 htmlを少しでも知っている人ならすぐにわかるように、<xsl:template match='/'></xsl:template>の中身はほとんど、HTMLファイルの構造そのままです。唯一なじみがないのは、<xsl:apply-templates select="....."/>という表現ですが、これはすでに上で説明しました。 ただ、//doctitle, //contens, //rank0となっています。要素名の前に付加されている//はなんでしょう。kelffaq.xmlを開き構造を見てください。次のような構造になっています。 <kelffaqDoc> <head> <doctitle /> <contents> <cnt_item/> </contents> </head> <rank0> 種々の要素 </rank0> </kelffaqDoc> '/'で流れ込むのはもっとも外側の<kelffaqDoc>です。(「流れ込む」は比喩的な表現です。) <doctitle>や<contents>や<rand0>は直接的には流れ込みません。 /kelffaqDoc/head/doctite /kelffaqDoc/head/contents /kelffaqDoc/root0 と表現すると、<xsl:template match="/">の"/"に対応するのは、先頭の"/"部分です。(ルートと呼びます)。 だから、 <xsl:template match="/"> <xsl:apply-templates select="doctitle"/> <xsl:apply-templates select="contents"/> <xsl:apply-templates select="rank0"/> </xsl:template> ではマッチしないのです。あいだに他の要素が挟まっているからです。 そこで、あいだに種々の要素が挟まるかも知れないけれど、とにかく下位にあるものを指定する、という意味で、//を前置します。 こうすることで、doctile, contents, rank0を処理できます。 doctitle,contens,rank0などのtemplateは、さらに下位の要素を処理するため、<xsl:apply-templates>を使い、新たな処理単位を呼んでいます。 これでXSLのおおよその構造はご理解いただけたと思います。 さらにXSLの詳細を知りたい方はW3Cの仕様書などをお読みください。左のLink集からたどれます。 次は「SARI関連」ページの生成を簡単に説明します。 「SARI関連」は、次の4つの部分で構成されています。
7. HTMLファイル生成
(1)ページタイトルなどのヘッダ部 (2)プログラムの一覧表 (3)各プログラムの詳細 (4)リンクと著作権などを書くフッタ部 これをXSLで作る場合、 <xsl:template match="/"> <html> <head> <title>Addins</title> </head> <body・・・> ヘッダ部生成のXSL 表形式生成のXSL 詳細説明生成のXSL フッタ部生成のXSL </body> </html> </xsl:template> という作りにすればいいでしょう。 上に<xsl:apply-templates select='...'>という処理を説明しましたが、もうひとつ、<xsl:call-template name='....'>という形式をよく使います。これは、流れ込んだノードに対して、マッチングを調べるのではなく、名前を指定して処理単位を呼び出すものです。 たとえば、表形式生成の処理単位の名前をmake_programlist, 詳細説明生成の処理単位の名前をmake_program_detailとするなら、 <xsl:template match="/"> <html> <head> <title>Addins</title> </head> <body・・・> ヘッダ部生成のXSL <xsl:call-template name='make_proglist' /> <xsl:call-template name='make_program_detail' /> フッタ部生成のXSL </body> </html> </xsl:template> <xsl:template name='make_proglist'> 実際の生成処理 </xsl:template> <xsl:template name='make_program_detail'> 実際の生成処理 </xsl:template> という構造になります。 処理単位に対してパラメタを渡すことができます。 データファイルをパラメタ化しておけば、処理単位を別のファイルの処理にも使用することができます。具体的には次のようにパラメタを指定し、受け取ります。 <xsl:template match="/"> <html> <head> <title>Addins</title> </head> <body・・・> ヘッダ部生成のXSL <xsl:call-template name='make_proglist' > <xsl:with-param name='file'>addinfiles.xml</xsl:with-param> </xsl:call-template> <xsl:call-template name='make_program_detail' > <xsl:with-param name='file'>addinfiles.xml</xsl:with-param> </xsl:call-template> フッタ部生成のXSL </body> </html> </xsl:template> <xsl:template name='make_proglist'> <xsl:param name='file' /> 実際の生成処理 </xsl:template> <xsl:template name='make_program_detail'> <xsl:param name='file' /> 実際の生成処理 </xsl:template> 上の例でわかるように、<xsl:with-param></xsl:with-param>を処理単位を呼び出す要素の下位要素にします。 呼び出される側の処理単位は、 <xsl:param name='....' />でパラメタを受け取ります。パラメタの値は$を前置して(たとえば$file)利用します。 こういう構造で, 表形式の処理と詳細説明の処理部分だけを抜き出して書いたのが、./xml/text/makeproglist.xslです。 makeproglist.xslファイルのなかに、 <xsl:template name='make_proglist'> ・・・・ </xsl:template> <xsl:template name='make_program_detail'> ・・・・ </xsl:template> が存在します。これらが本体から呼び出されるわけです。 別ファイルにしたのは、他のページを作成するとき再利用できるからです。 ただ、別ファイルにしたので、これを本体relate.xslに組み込む必要があります。<xsl:import>という処理を使います。 <xsl:import href='makeproglist.xsl' /> という一行を書いておけば読み込んでくれます。 イメージファイルの都合上、ヘッダ部とフッタ部は省略していますが、addinfiles.xmlから「SARI関連」ページを生成するためのXSLファイルが、./xml/text/relate.xslです。これが本体です。これをご覧いただき、makeproglist.xslを見ていただくと、実際の処理がすべてわかると思います。(htmlの知識が必要ですが) 「XMLの変換」の項で説明したように、XMLとXSLからHTMLファイルを生成するには、XSLTプロセッサを使います。
XSLTプロセッサとしてXTを使い、上のaddinfiles.xmlとrelate.xslから、relate.htmlを生成する場合、コマンドラインから X:\somedir>XT addinfiles.xml relate.xsl > relate.html を実行します。 でも、relate.xslをじっくりご覧になった方はすでにお気づきかもしれません。 relate.xslのルートを処理する、 <xsl:template select='/'> </xsl:template> の中には、ノードのマッチを確かめる<xsl:apply-templates select='....'>がひとつも使われていません。<xsl:call-template name='....'>を使い、別ファイルmakeproglist.xslに書かれた処理単位を順に呼び出しているだけです。その呼び出しのパラメタとしてファイル名addinfiles.xmlが渡されています。 つまり、 X:\somedir>XT addinfiles.xml relate.xsl > relate.html のaddinfiles.xmlは、ここでは意味がありません。他のどんなXMLファイル名を書いてもいいです。XTの書式を整えるために書いているだけです。 混乱させるかもしれません。 要は、XTのコマンドラインパラメタ、addinfiles.xmlを変換したわけではないということです。<xsl:call-template>のパラメタとして渡されたファイルのデータからHTMLを構築したわけです。「XMLファイルを変換する」というより、処理の実態は、「XMLデータからHTMLを生成する」と言ったほうが近いということです。 |