XML, XSL


「ローマコイン」のページを作るのに XML+XSL+WSH を使ってみました。

やりたかったことは

  1. フレーム版と非フレーム版を作る。
  2. フレーム版は左のフレームを各皇帝へのリンク集にする。 右のフレームに皇帝別のコインの画像と説明を書く。 これは皇帝毎に別ファイルにする( 画像表示をともなうので1つのファイルにまとめると重いので)。
    右のフレームには、前の皇帝と次の皇帝のファイルへのリンクを表示したい。
  3. 非フレーム版は一番上に各皇帝へのリンクを表示する。
  4. IE5.0 だけでなく、ネスケでも読めるページにする。
以上のようなことを普通にHTMLファイルを書いて実現することも もちろん可能だが、同じ説明文をフレーム版と非フレーム版に 書かなければならないし、同じ皇帝の名前を何カ所も書くことに なる。また、リンクを何カ所も張っているので、途中に一人皇帝を 追加したりするときなどメンテナンスが大変困難である。

そこで登場するのがXML

1つの XMLでデータを書いておけば、XSLを切り替えるだけで 別のスタイルで表示することができる。 自分で分かりやすいタグを定義して使えるので、メンテナンスも楽。
現時点では IE5.0以上が無いと XML を直接表示することが できないので、予め WSH(Windows Scripting Host) を使って、XML から HTML に変換してから サーバにアップロードすることにした。
もし、Web サーバが Windows NT であれば、 先にHTMLファイルを作っておく必要はなく, asp を使ってサーバサイドで処理することも可能である。 こうやるともっと楽なはず。
perl のモジュールにも XMLパーサはあるので、 CGIでもやれるはずである。

XMLからHTMLへの変換

無料で入手できるXSLTプロセッサには、msxsl, Xalan, XT などがある。msxsl はたぶん一番お手軽。
他にはDOMオブジェクトを使って、自分の好みのプログラム言語で変換することも出来る。 私の場合は、WSHを使っている。msxsl や xalan を使うとコマンドライン一発でhtmlへの変換が出来るのに、わざわざ スクリプトを使うのは、transformNodeメソッドで変換する前にDOMツリーを操作することができる。」 という点に魅力を感じているからである。
link.xmlとlink.xslからlink.htmlをつくるスクリプトをVBS で書けば、こんな感じになる。
option explicit
conv "link.xml", "link.xsl", "link.html"

sub conv(xmlpath, stylesheetpath, htmlpath)
	dim xmldoc, stylesheet, result, str, F_IN, FS, F_OUT
	set FS=createobject("Scripting.FileSystemObject")
	set F_IN=FS.GetFile(xmlpath)
 	set F_OUT=FS.CreateTextFile(htmlpath, 1)
	set xmldoc=createobject("MSXML2.DomDocument")
	xmldoc.async=false
	xmldoc.load(xmlpath)
	set stylesheet=createobject("MSXML2.Domdocument")
	stylesheet.async=false
	stylesheet.load(stylesheetpath)
	str = xmldoc.transformNode(stylesheet)
	str=okikae(str, "UTF-16", "Shift_JIS")
	str=okikae(str, "&", "&")
	str=okikae(str, "<br/>", "<br />")
	F_OUT.Write str
	F_OUT.Close
end sub

function okikae(inp_str, org, dest)
	dim n
	if len(org)=0 then okikae=inp_inp_str:return
	n=instr(1, inp_str, org)
	do while n>0
		inp_str=left(inp_str,n-1) & dest & mid(inp_str, n+len(org))
		n=instr(1, inp_str, org)
	loop
	okikae=inp_str
end function

同様のものを Perlスクリプトで書くと、こんな感じ。このスクリプトの最後の方には 出力されるhtmlファイルのタイムスタンプをソースのxmlファイルのタイムスタンプに あわせるコードを付け加えてみた。
&conv("link.xml", "link.xsl", "link.html");

sub conv{
	my($xmlpath, $stylesheetpath, $htmlpath)=@_;
	my($xmldoc, $stylesheet, $str, $n);
	$xmldoc=$WScript->CreateObject("MSXML2.DomDocument");
	$xmldoc->{async}=0;
	$xmldoc->load($xmlpath);
	$stylesheet=$WScript->CreateObject("MSXML2.DomDocument");
	$stylesheet->{async}=0;
	$stylesheet->load($stylesheetpath);
	$str=$xmldoc->transformNode($stylesheet);
	$str=~s/UTF-16/Shift_JIS/;     # transformNodeメソッドが勝手に UTF-16 と書いてくれるので修正
	$str=~s/&amp;/&/ig;
	$str=~s"<br/>"<br />"ig;
	open(F_OUT, ">$htmlpath")||die "Cannot write $htmlpath";
	print F_OUT $str;
	close(F_OUT);
	$tsrc= time()-(-M $xmlpath)*24*3600;  # この2行で出力ファイルのタイムスタンプを
	utime  $tsrc, $tsrc, $htmlpath;       # 入力ファイルのタイムスタンプにあわせている。
}


実験してみたい方は、coinxml.lzh を適当なフォルダーで解凍してから、 _coin.vbs を実行して下さい。そのフォルダーに非フレーム版の html ファイルや、 皇帝別の html ファイルが作られます。ただし、必要な画像が 含まれていないので、画像のところは「×印」で表示されます。

いろいろ

時間割表(jikan.lzh) xml で時間割を作ってみました。ソースを見るとメンテナンスが楽なのが分かると思います。(とっても単純だけど、学校関係者には役立つかもしれません。font 関係のところは必要に応じて修正して下さい。)
その xsl はここ

Copyright(C) augustus

古代ローマ(ローマの歴史とコイン)
古代ローマローマ帝国の歴史とコイン