トップページをXMLとXSLTで作る

はじめに

このサイトは,これまでデザインを何度か変えていますが,末端のページまで整合性を持たせて修正する手間は結構大変なものがあります.そのため,古いデザインのまま放置している箇所もあります.そこで,各ページ固有の内容はXMLで,共通している部分はXSLTで作成できれば,全体を統一できて,修正も簡単ではないかと考えたわけです.まずトップページを実験台としました.

以下の方針を立てました.

XMLファイルの作成

2002.1.13時点のトップページ(index.html)から,XMLファイル(index.xml)を作成します.

<!-- 2002.1.13のトップページ(index.html)-->
<?xml version="1.0" encoding="Shift_JIS"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="ja" xml:lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS" />
<meta http-equiv="Content-Script-Type" content="text/javascript" />
<meta name="wwwc" content="2002.1.13 歳時記・備忘録更新" />
<link rel="stylesheet" title="Recommends" type="text/css" href="css.css" />
<link rev="made" href="mailto:foo@bar" />
<title>眠る猫の頁</title>
</head>

<body>
<div class="Menu">
  眠る猫の頁<br />
  表紙&nbsp;|&nbsp;
  <a href="whatsnew/index.html">新着</a>&nbsp;|&nbsp;
  <a href="saijiki/index.html">歳時記</a>&nbsp;|&nbsp;
  <a href="ryokoki/index.html">旅行記</a>&nbsp;|&nbsp;
  <a href="hyoryuki/index.html">漂流記</a>&nbsp;|&nbsp;
  <a href="biboroku/index.html">備忘録</a>&nbsp;|&nbsp;
  <a href="zatsuroku/index.html">雑録</a>
</div>

<h1>眠る猫の頁</h1>
<p><img width="333" height="250" src="cat.jpg" alt="" /></p>

<dl>
  <dt><a href="whatsnew/index.html">新着</a></dt>
  <dd class="ContentDef">2002.1.13
      <ul>
    <li><a href="saijiki/index.html">歳時記</a>に2002.1.6から2002.1.12までを追加.</li>
    <li><a href="biboroku/index.html">備忘録</a>に「SQL*PlusのバッファでSQLを編集」を追加.</li>
    </ul>
  </dd>

  <dt><a href="saijiki/index.html">歳時記</a></dt>
  <dd class="ContentDef">日々の出来事など.</dd>

  <dt><a href="ryokoki/index.html">旅行記</a></dt>
  <dd class="ContentDef">旅先での写真や駄文を.</dd>

  <dt><a href="hyoryuki/index.html">漂流記</a></dt>
  <dd class="ContentDef">システム開発への私見です.</dd>

  <dt><a href="biboroku/index.html">備忘録</a></dt>
  <dd class="ContentDef">教えてもらったことやできたことを忘れないうちに.</dd>

  <dt><a href="zatsuroku/index.html">雑録</a></dt>
  <dd class="ContentDef">その他雑多なものが色々.</dd>
</dl>

<div class="Banner">
  <a href="http://www.nakka.com/wwwc/"><img width="88" height="31" src="http://www.nakka.com/wwwc/wwwc_meta.png" alt="WWWC META Check" /></a>
  <a href="http://validator.w3.org/check/referer"><img width="88" height="31" src="http://www.w3.org/Icons/valid-xhtml10" alt="Valid XHTML 1.0!" /></a>
  <a href="http://jigsaw.w3.org/css-validator/check/referer"><img width="88" height="31" src="http://jigsaw.w3.org/css-validator/images/vcss" alt="Valid CSS!" /></a>
</div>

<hr />
<div class="MailTo">
  ご意見・ご感想は<a href="mailto:foo@bar">foo@bar</a>まで.
</div>

<div class="AccessLog">
  <script type="text/javascript">
  <!--
  document.write("<img src=\"/cgi-bin/user/sasa/aclogsJS.cgi?id=index&ref=" + document.referrer + "\" />");
  -->
  </script>
  <img src="/cgi-bin/user/sasa/aclogsIMG.cgi?index" alt="" />
</div>
</body>
</html>
<!-- 2002.1.13のトップページから作ったxml(index.xml) -->
<root>
<head>
  <meta name="wwwc" content="2002.1.13 歳時記・備忘録更新" />
</head>
<body>
  <h1>眠る猫の頁</h1>
  <p><img width="333" height="250" src="cat.jpg" alt="" /></p>
  
  <dl>
    <dt><a href="whatsnew/index.html">新着</a></dt>
    <dd class="ContentDef">2002.1.13
        <ul>
      <li><a href="saijiki/index.html">歳時記</a>に2002.1.6から2002.1.12までを追加.</li>
      <li><a href="biboroku/index.html">備忘録</a>に「SQL*PlusのバッファでSQLを編集」を追加.</li>
      </ul>
    </dd>
  
    <dt><a href="saijiki/index.html">歳時記</a></dt>
    <dd class="ContentDef">日々の出来事など.</dd>
  
    <dt><a href="ryokoki/index.html">旅行記</a></dt>
    <dd class="ContentDef">旅先での写真や駄文を.</dd>
  
    <dt><a href="hyoryuki/index.html">漂流記</a></dt>
    <dd class="ContentDef">システム開発への私見です.</dd>
  
    <dt><a href="biboroku/index.html">備忘録</a></dt>
    <dd class="ContentDef">教えてもらったことやできたことを忘れないうちに.</dd>
  
    <dt><a href="zatsuroku/index.html">雑録</a></dt>
    <dd class="ContentDef">その他雑多なものが色々.</dd>
  </dl>
  
  <div class="Banner">
    <a href="http://www.nakka.com/wwwc/"><img width="88" height="31" src="http://www.nakka.com/wwwc/wwwc_meta.png" alt="WWWC META Check" /></a>
    <a href="http://validator.w3.org/check/referer"><img width="88" height="31" src="http://www.w3.org/Icons/valid-xhtml10" alt="Valid XHTML 1.0!" /></a>
    <a href="http://jigsaw.w3.org/css-validator/check/referer"><img width="88" height="31" src="http://jigsaw.w3.org/css-validator/images/vcss" alt="Valid CSS!" /></a>
  </div>
</body>
</root>

独自に作ったタグはルートタグ<root></root>だけです.それ以外はXHTMLで書いた,元のindex.htmlのタグをそのまま使っています.HTMLからXHTMLに変えた効果が,こんなところに現れました.

XSLTを作る

作成したXMLファイルからブラウザで表示できるXHTMLファイルを作るためのXSLTです.

<!-- index.xsl -->
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" encoding="UTF-8" indent="no"/>
  <xsl:output
    method="xml"
    encoding="UTF-8"
    indent="yes"
    doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
    doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"/>

<xsl:template match="root">
  <html xmlns="http://www.w3.org/1999/xhtml" lang="ja" xml:lang="ja">
  <head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
  <meta http-equiv="Content-Script-Type" content="text/javascript" />
  <xsl:apply-templates select="head/meta"/>  <!-- index.xmlに定義したmetaタグを表示 -->
  <link rel="stylesheet" title="Recommends" type="text/css" href="css.css" />
  <link rev="made" href="mailto:foo@bar" />
  <title><xsl:value-of select="body/h1"/></title>  <!-- titleにはindex.xmlのh1を表示 -->
  </head>
  <body>

  <div class="Menu">
    <xsl:value-of select="body/h1"/><br />
    表紙<xsl:call-template name="menu_div"/> <!-- &nbsp;|&nbsp;と出力するための名前付きテンプレート.定義はファイルの下方 -->
    <a href="whatsnew/index.html">新着</a><xsl:call-template name="menu_div"/>
    <a href="saijiki/index.html">歳時記</a><xsl:call-template name="menu_div"/>
    <a href="ryokoki/index.html">旅行記</a><xsl:call-template name="menu_div"/>
    <a href="hyoryuki/index.html">漂流記</a><xsl:call-template name="menu_div"/>
    <a href="biboroku/index.html">備忘録</a><xsl:call-template name="menu_div"/>
    <a href="zatsuroku/index.html">雑録</a>
  </div>

  <xsl:apply-templates select="body"/> <!-- index.xmlのbodyタグの中を表示 -->

  <hr />
  <div class="MailTo">
    ご意見・ご感想は<a href="mailto:foo@bar">foo@bar</a>まで.
  </div>

  <div class="AccessLog">
    <script type="text/javascript">
    <xsl:comment>
    <![CDATA[
    document.write("<img src=\"/cgi-bin/user/sasa/aclogsJS.cgi?id=index&ref=" + document.referrer + "\" />");
    ]]>
    </xsl:comment>
    </script>
    <img src="/cgi-bin/user/sasa/aclogsIMG.cgi?index" alt="" />
  </div>
  </body>
  </html>
</xsl:template>

<xsl:template match="meta">
  <xsl:copy-of select="."/> <!--マッチしたタグ自身を含む-->
</xsl:template>

<xsl:template match="body">
  <xsl:copy-of select="*"/> <!--マッチしたタグ自身を含まない-->
</xsl:template>

<xsl:template name="menu_div">
  <xsl:text disable-output-escaping="yes">&amp;nbsp;|&amp;nbsp;</xsl:text>
  <!-- &nbsp;は該当する実態参照がXSLTにないらしく,変換時にエラーになる.&nbsp;と出力したい場合は,disable-output-escapint="yes"として&amp;nbsp;と記述する.たくさんある場合は名前付きテンプレートにすると便利.-->
</xsl:template>
</xsl:stylesheet>

XSLTプロセッサで変換

XMLファイルとXSLTファイルができたので,XSLTプロセッサでXHTMLに変換します.XSLTプロセッサはXT(Java版ではなくWin32 executebleの方)とXalan-Javaを使いました.必要なのはXTかXalan-Javaどちらか一つで,両方必要なわけではありません.インストール・起動方法の詳細はそれぞれのウェブやファイルを見てください.

XTでindex.xslを使ってindex.xmlをindex.htmlに変換するにはこのようにコマンドを打ち込みます.

c:\>"%ProgramFiles%\xt\xt.exe" index.xml index.xsl index.html

Jalan-JavaはJava版なので,classpathの指定が必要です.なお,使ったJavaのバージョンはは1.3.1_01です.

c:\>set classpath=%ProgramFiles%\xalan-j\bin\xalan.jar;%ProgramFiles%\xalan-j\bin\xml-apis.jar;%ProgramFiles%\xalan-j\bin\xerces.jar;.
c:\>java org.apache.xalan.xslt.Process -in index.xml -xsl index.xsl -out index.html

いちいち打ち込むのは大変なので,バッチファイルを作っておきましょう.

set classpath=%ProgramFiles%\xalan-j\bin\xalan.jar;%ProgramFiles%\xalan-j\bin\xml-apis.jar;%ProgramFiles%\xalan-j\bin\xerces.jar;.
java org.apache.xalan.xslt.Process -in %1 -xsl %2 -out %3

できあがったファイルを整形

XTはこのようなindex.htmlを作成します.Xalan-Javaも似たようなものです.

<?xml version="1.0" encoding="utf-8"?>

  
  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
  
  <html lang="ja" xml:lang="ja" xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/><meta http-equiv="Content-Script-Type" content="text/javascript"/><meta name="wwwc" content="2001.12.30歳時記・備忘録更新"/><link rel="stylesheet" title="Recommends" type="text/css" href="css.css"/><link rev="made" href="mailto:foo@bar"/><title>眠る猫の頁</title></head><body><div class="Menu">眠る猫の頁<br/>
    表紙&nbsp;|&nbsp;<a href="whatsnew/index.html">新着</a>&nbsp;|&nbsp;<a href="saijiki/index.html">歳時記</a>&nbsp;|&nbsp;<a href="ryokoki/index.html">旅行記</a>&nbsp;|&nbsp;<a href="hyoryuki/index.html">漂流記</a>&nbsp;|&nbsp;<a href="biboroku/index.html">備忘録</a>&nbsp;|&nbsp;<a href="zatsuroku/index.html">雑録</a></div><h1>眠る猫の頁</h1><p><img width="333" height="250" src="cat.jpg" alt=""/></p><dl>
    <dt><a href="whatsnew/index.html">新着</a></dt>
    <dd class="ContentDef">2001.12.30
        <ul>
      <li><a href="saijiki/index.html">歳時記</a>に2001.12.23から2001.12.29までを追加.</li>
      <li><a href="biboroku/index.html">備忘録</a>に「Perl−モジュールのあるディレトクリの指定」を追加.</li>
      </ul>
    </dd>
  
    <dt><a href="saijiki/index.html">歳時記</a></dt>
    <dd class="ContentDef">日々の出来事など.</dd>
  
    <dt><a href="ryokoki/index.html">旅行記</a></dt>
    <dd class="ContentDef">旅先での写真や駄文を.</dd>
  
    <dt><a href="hyoryuki/index.html">漂流記</a></dt>
    <dd class="ContentDef">システム開発への私見です.</dd>
  
    <dt><a href="biboroku/index.html">備忘録</a></dt>
    <dd class="ContentDef">教えてもらったことやできたことを忘れないうちに.</dd>
  
    <dt><a href="zatsuroku/index.html">雑録</a></dt>
    <dd class="ContentDef">その他雑多なものが色々.</dd>
  </dl><div class="Banner">
    <a href="http://www.nakka.com/wwwc/">
      <img width="88" height="31" src="http://www.nakka.com/wwwc/wwwc_meta.png" alt="WWWC META Check"/></a>
    <a href="http://validator.w3.org/check/referer">
      <img width="88" height="31" src="http://www.w3.org/Icons/valid-xhtml10" alt="Valid XHTML 1.0!"/></a>
    <a href="http://jigsaw.w3.org/css-validator/check/referer">
      <img width="88" height="31" src="http://jigsaw.w3.org/css-validator/images/vcss" alt="Valid CSS!"/></a>
  </div><hr/><div class="MailTo">
    ご意見・ご感想は<a href="mailto:foo@bar">foo@bar</a>まで.
  </div><div><script type="text/javascript"><!--
    
    document.write("<img src=\"/cgi-bin/user/sasa/aclogsJS.cgi?id=index&ref=" + document.referrer + "\" />");
    
    --></script><img src="/cgi-bin/user/sasa/aclogsIMG.cgi?index" alt=""/></div></body></html>

ブラウザでの表示には支障ありませんが,見栄えが悪いので,perlとsedで整形します.

#!/usr/bin/perl -p
#適当に改行とタブを入れる format.pl

s/^\t//g;
s/\sxmlns=""//g;
s/^\t+(<\!DOCTYPE.*)/$1/;
s/^\t+(<html.*)/$1/;
s!(<meta[^>]*/>|<link[^>]*/>|<title>|<script[^>]*>|<\!--)!\n\t$1!g;
s!(</?head>|</?body>|<div[^>]*>|<h1>|<p>|<dl>|<hr/>|</html>)!\n$1!g;
s!(</script>)(<img[^>]*>)!\n\t$1\n\t$2!g;
s!<br/><a!<br/>\n\t<a!g;
s/(<div.*>)(<a)/\1\n\t$2/g;
s!></div>!>\n</div>!g;
s/>(<h\d>)/>\n$1/g;
s!<(.*)/>!<$1 />!g;
s/^\t+$//g;
#タブと空白だけの行を削除 format.sed
/^[ | ]*$/d

Windowsで動くperlとsedを持っていないので,cygwinで動くbashで実行しました.

> "${PROGRAMFILES}/xt/xt.exe" index.xml index.xsl index_unformatted.html
> format.pl index_unformatted.html|sed -f format.sed>index.html
> java org.apache.xalan.xslt.Process -in index.xml -xsl index.xsl -out index_unformatted.html
> format.pl index_unformatted.html|sed -f format.sed>index.html

こんなindex.htmlになります.

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html lang="ja" xml:lang="ja" xmlns="http://www.w3.org/1999/xhtml">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
  <meta http-equiv="Content-Script-Type" content="text/javascript" />
  <meta name="wwwc" content="2001.12.30歳時記・備忘録更新" />
  <link rel="stylesheet" title="Recommends" type="text/css" href="css.css" />
  <link rev="made" href="mailto:foo@bar" />
  <title>眠る猫の頁</title>
</head>
<body>
<div class="Menu">眠る猫の頁<br />
  表紙&nbsp;|&nbsp;<a href="whatsnew/index.html">新着</a>&nbsp;|&nbsp;<a href="saijiki/index.html">歳時記</a>&nbsp;|&nbsp;<a href="ryokoki/index.html">旅行記</a>&nbsp;|&nbsp;<a href="hyoryuki/index.html">漂流記</a>&nbsp;|&nbsp;<a href="biboroku/index.html">備忘録</a>&nbsp;|&nbsp;<a href="zatsuroku/index.html">雑録</a>
</div>
<h1>眠る猫の頁</h1>
<p><img width="333" height="250" src="cat.jpg" alt="" /></p>
<dl>
  <dt><a href="whatsnew/index.html">新着</a></dt>
  <dd class="ContentDef">2001.12.30
      <ul>
    <li><a href="saijiki/index.html">歳時記</a>に2001.12.23から2001.12.29までを追加.</li>
    <li><a href="biboroku/index.html">備忘録</a>に「Perl−モジュールのあるディレトクリの指定」を追加.</li>
    </ul>
  </dd>
  <dt><a href="saijiki/index.html">歳時記</a></dt>
  <dd class="ContentDef">日々の出来事など.</dd>
  <dt><a href="ryokoki/index.html">旅行記</a></dt>
  <dd class="ContentDef">旅先での写真や駄文を.</dd>
  <dt><a href="hyoryuki/index.html">漂流記</a></dt>
  <dd class="ContentDef">システム開発への私見です.</dd>
  <dt><a href="biboroku/index.html">備忘録</a></dt>
  <dd class="ContentDef">教えてもらったことやできたことを忘れないうちに.</dd>
  <dt><a href="zatsuroku/index.html">雑録</a></dt>
  <dd class="ContentDef">その他雑多なものが色々.</dd>
</dl>
<div class="Banner">
  <a href="http://www.nakka.com/wwwc/">
    <img width="88" height="31" src="http://www.nakka.com/wwwc/wwwc_meta.png" alt="WWWC META Check" /></a>
  <a href="http://validator.w3.org/check/referer">
    <img width="88" height="31" src="http://www.w3.org/Icons/valid-xhtml10" alt="Valid XHTML 1.0!" /></a>
  <a href="http://jigsaw.w3.org/css-validator/check/referer">
    <img width="88" height="31" src="http://jigsaw.w3.org/css-validator/images/vcss" alt="Valid CSS!" /></a>
</div>
<hr />
<div class="MailTo">
  ご意見・ご感想は<a href="mailto:foo@bar">foo@bar</a>まで.
</div>
<div class="AccessLog">
  <script type="text/javascript">
  <!--
  document.write("<img src=\"/cgi-bin/user/sasa/aclogsJS.cgi?id=index&ref=" + document.referrer + "\"  />");
  -->
  </script>
  <img src="/cgi-bin/user/sasa/aclogsIMG.cgi?index" alt="" />
</div>
</body>
</html>

参考文献

XSLTプロセッサ

その他

xyzzy
愛用しているemacs風エディタ.UTF-8のファイルも編集可能.
cygwin
Windowsで動くUNIXツールの数々.