Kazusoft HPを素材に
KELFエクスポート機能の使い方(例-3B)
INDEX
KAZUSOFT
KELFメインページ
エクスポート機能の使い方
NetNewsログのXML化
FAQ集を作る
XMLの変換(HTML化)
KELFをXMLエディタ風に
KazusoftのHPを素材に
(番外)このハウツーの作成
LINKs
W3C仕様関係各種の情報XSLTプロセッサ
1. プログラムリスト
もっともわかりやすいと思うので、「SARI関連」ページをとりあげます。テキストエディタSARIのアドインプログラム類を公開しているページです。
(このハウツー執筆時点のものを使います。時間がたつとデザインや内容を変更しているかもしれません。あらかじめご了承ください。)




ページタイトルを書いたヘッダ部と、著作権などを表示したフッタ部を除外すると、このページは、プログラムの一覧を表形式で表示したものと、それらのプログラムの詳しい説明部分からなりたっています。
この表形式の部分と詳細説明の部分は同じXMLデータから生成しており、そのXMLデータは、KELFの下記文書からエキスポート生成したものです。






2. 対応する文法
addinfiles.txtをご覧いただけば想像していただけるように、この文書は、文法のタイトルパターンとして、

^!0-(.+)$
^\s*!1-(.+)$
^\s*!2-(.+)$
^\s*!3-(.+)$
^\s*!4-(.+)$
^\s*!5-(.+)$
^\s*!6-(.+)$

を設定し、「タイトルの種類で階層構造を作る」をチェックして作成したものです。(!1から!6で、\s*を入れて行頭空白を許容しているのは、階層によるインデントを意図したものです。しかし実際は使っていません。)
上と同じパターンを強調単語に指定すると構造が見やすくなるでしょう。

文書構造の概観をXML風に書けば、次のようになります。

<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>要素のひとつが、ひとつのプログラムに対応します。文書内にはいくつかの<program>要素が並列に存在します。

<program>要素の下部要素<explanation>は、そのプログラムについての詳しい説明です。改行を生かしたいので、この要素については、エクスポート時に、「基本的な設定」ページで「段落をタグで囲む」をチェックして、段落を<p>で囲むようにします。
<abstract>は一行説明です。表形式の表示でこの部分を使います。一行ですので段落を囲む必要はありません。

プログラムに画像がある場合はイメージファイルを関連づけます。<image>要素です。
ただ、画像をそのまま表示すると、ダイアルアップ接続の場合、ページ表示に時間がかかりすぎる恐れがあります。そのため、別に小さな画像を用意しておき、その画像をクリックすれば、プログラムの画像を表示するようにしています。javascriptを使います。そのトリガーにするのが<map>要素です。

<marker>要素は、アンカーのnameかidとして利用するためです。

他はだいたい要素名から想像していただけるでしょう。


3. 埋め込み属性
addinfiles.txt中、ところどころに、

~xattr;

ではじまる行があります。埋め込み属性です。
一定の形式で記入しておくことにより、エクスポート時に、自動的に属性を設定します。属性行と認識した場合、その行は本文から除去してエクスポートします。
KELFのヘルプには書いてありますが、再述すると、

 (行頭)接頭辞 + 属性名 + 「=」 + 値(行末)

という形式です。この文書の場合、接頭辞は~xattr;です。
また、この文書では、ほとんどの属性をCDATA #IMPLIEDで扱っていますので、使用していませんが、属性定義を文書中に埋め込んでおくことも可能です。その形式は、上とまったく同じで、デフォルト接頭辞は~xattrdef;です。

これらの埋め込み属性を有効にするには、エクスポート時に、「その他の要素名や属性名の設定」ページで、「文書中の埋め込み属性を検索する」をチェックしなければなりません。

addinfiles.txtでは、主に画像の配置などを埋め込み属性を使って決めています。
もちろん、XSL作成段階で、画像の配置などは任意に決定できるわけですが。



4. XMLファイルを作成
エクスポート機能で、

  addinfiles.txt  ⇒  addinfiles.xml

を作成します。
ウィザードの最初のページで、「セクションタイトルを要素名にする」と「一部分を抽出して要素名にする」をチェックしておきます。この場合、抽出用の正規表現は^!\d+-(.+)$で、マッチさせる部分は1です。
「その他の要素名や属性名の設定」ページで、「文書中の埋め込み属性を検索する」をチェックするのも忘れずに。
なを最後のページで、「不要なデフォルトid属性を出力しない」をチェックしておくと、セクションに対して付加されるデフォルトid属性の出力が抑制できます。このオプションは、セクション間リンクを作る設定がどこかにひとつでも存在すると、選択できません。


これでデータのXMLは作成できたわけです。
これをブラウザ上でどう表現するかです。
ブラウザで表示するためにはXSLを書かなければなりません。



5. XSL言語の構造
XSLについて解説するのは筆者の任ではありません。ただ、まったく書かないのも不親切と思いますので、XSLを知らない人のためのとっかかりだけを書きます。XSLをご存知の方はこれ以降を読んでいただく必要はありません。

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関連」ページの生成を簡単に説明します。


6. ページの組み立て
「SARI関連」は、次の4つの部分で構成されています。

(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の知識が必要ですが)






7. 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を生成する」と言ったほうが近いということです。






エクスポート機能の使い方 | NetNewsログのXML化 | FAQ集を作る
XMLの変換(HTML化) | KELFをXMLエディタ風に | KazusoftのHPを素材に
(番外)このハウツーの作成


作成:2002年1月15日
Copyright(C) 2002 Kazuhiro Kito(k-kito@kazusoft.com)