XMLベースのウェブサイトを構築する(1)

ページ情報
制作日
2004-01-20
最終更新日
2004-01-20
参照用URI
http://www.arielworks.net/articles/2004/0120a
分野
ページ内目次

4半期中間報告

3ヶ月ほど運用してみてだいぶ設計が決まったので、継ぎ接ぎで作って来たシステムを今回一新した。XMLベースのウェブサイトの一例として大まかな設計を書いておく。

概要

XMLファイルへのリクエストをmod_rewriteでフックし、PHPによりリクエストされたXMLファイルをXHTMLにXSLTで変換する。クライアントが実際に受け取るのはXHTMLファイルなのでブラウザのXMLサポートが完全でなくても問題がない。またサイト運営者はサイト内の共通部分を排除したXML文章を書くことが出来るので管理が楽になる。

Himmel

現在このサイトは各URIに対応したXMLファイルによって構成されている。ディレクトリがリクエストされた場合はindex.xmlが返される。各XMLファイルは文章として独立しており、実際はそのままでも運用は可能である。しかし、現状ではブラウザのXML、XSLTのサポートが十分ではないことからXMLファイルへのリクエストをフックし、サーバサイドでXHTMLに変換してからクライアントに送信している。

XMLからXHTMLへの変換は「Himmel」というスクリプト群で実装されている。

まず、XMLファイルへリクエストが有った場合、Apacheのmod_writeによりリクエストをフックし、リクエストされたXMLファイルのパスを引数としてsora.phpを実行する。

RewriteEngine on
RewriteRule ^(.*/)$ himmel/sora.php?id=/$1
RewriteRule ^$ himmel/sora.php?id=/

ところで、このサイト内では1ページ1ディレクトリ方式を採用している。なぜかと言うと、1つのページに1つのディレクトリを作ることによってページ内で使用されている画像ファイルやスクリプトファイルを1ヵ所にまとめる事が出来るからである。画像スクリプトを別のディレクトリに保存しているとページを移動するときや削除する時に消し忘れ、実際は使用されていないファイルが残存してしまうことがある。

このように各ページの構成ファイルをディレクトリごとに纏めて置いた方が管理が楽である。

次に、このサイト内では各記事はIDで管理されている。最初はXMLファイル内にIDを書こうかとも考えたのだが、一意な文字列が必要ならパスをIDとすれば良いことに気が付いた。パス自体をIDとすることによってXMLファイルを移動してもファイル内はいじらなくて済む。ちなみにこの記事のIDは「/articles/2004/0121a/」だ。「index.xml」部分は省略する。リンクを張る際もIDがそのままパスになる。

以上のことよりXMLファイルのIDを元にRewriteRuleを設定すればよい。

1つ目のルールの「^(.*/)$」は「/links/」や「/works/fb2k/」などにマッチする。1ページ1ディレクトリ方式なのでこのルールが有れば全てのXMLファイルにマッチする。逆に「/works/fb2k/install/ss_01.png」の様なフックする必要がない構成ファイルにはマッチしない。

もし何らかの理由で「/works/hoge.xml」などのファイル名もフックしたい場合はそのファイルがあるディレクトリの.htaccess、「/works/.htaccess」に適当なルールを追加すればいい。

2つ目のルールは「http://www.arielworks.net/」がリクエストされた時のルールだ。「/」にはマッチしないので別にルールを作る必要があった。

sora.php

sora.phpはインタフェースモジュールでlemmih.incをrequire()する。ほぼ全ての関数がlemmih.incに含まれているのでsora.phpが行うのは変数の引き渡しだけである。これは実際の処理をlemmih.incに行わせることで「/foo/bar.php」のような動的ページでもlemmih.incを呼び出すで同じ書式のXHTMLファイルを出力出来るようにするためだ。

sora.phpが引き渡す変数は記事IDとその記事の構成ファイル(ここでは実体参照で置換されるXMLファイル等)のリストである。正確なページの更新時間を得るために構成ファイルの更新時間も調べなければならない。

lemmih.inc

lemmih.incは呼び出されると記事IDに対応したXMLデータをXSLTによってXHTMLに変換する。またHTTPレスポンスヘッダの出力もここで行う。

sora.phpは記事IDを持ってくるが、動的ページの場合はXMLファイルが存在しないので直接XMLデータを受け取れるようにもしてある。

この時点でXMLデータは以下の書式である。

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

<article version="2003-11-17" xml:lang="ja">

<head>
    <title>記事のタイトル</title>
    <date>
        <year>記事の制作年</year>
        <month>記事の制作月</month>
        <day>記事の制作日</day>
    </date>
    <category>
        <item>記事の分野(Articlesのみ)</item>
    </category>
</head>

<body lup="disable">


<p>文章など</p>


<section>
<head>
    <title>章のタイトル1</title>
    <id>章のID</id>
</head><body>

<p>文章など</p>


<section>
<head>
    <title>章のタイトル1.1</title>
    <id>章のID</id>
</head><body>

<p>文章など</p>

</body></section>


</body></section>


<section>
<head>
    <title>章のタイトル2</title>
    <id>章のID</id>
</head><body>

<p>文章など</p>

</body></section>


</body>

</article>

XHTML2.0の構造に近いが、この書式では各セクションがそれぞれhead要素を持っている。この例では指定していないが、各セクションに制作日を記入したりカテゴリーを指定することも出来る。つまり、article要素は名前は違うがsection要素と等価であり、完全に入れ子状態になっている。

このため、複数のXMLファイルをつなげればそのままそれが1つのXMLファイルとなり、日記型のコンテンツなどでは便利だと思われる。

基本的に各XMLファイルはこの書式で保存されており、動的に生成するXMLデータもこの形式で引き渡される。

XHTMLに変換が終われば後は出力して処理は完了である。

アドバイスなど

XMLベースのサイトを作るに当たって最初に考えたのは将来的にはPHPの助けを借りず、XMLのみで構成することになるだろう、ということだ。そのためPHPが無くてもXMLだけでサイトとして完結していなければならない。PHPはリクエストをフックするだけの控えめな存在で良いのだ。

フックの方法としてまず最初に行ったのは同名のファイル、例えば「index.php」などを各ページ(ディレクトリ)に置く方法だった。.htaccessでDirectoryIndexを使ってindex.phpの優先度を上げれば自動的にフックされることになる。あとはindex.phpでlemmih.incを呼び出せば良い。

しかしこの方法は各ページごとにindex.phpを作らなければいけないため、index.phpに変更の必要が生じると全ページの変更作業が必要となる。そのため、ページ数が増えてくると保守が大変になってしまった。そこで考えたのがmod_rewriteによるフックなのだが、上記の通りなかなかうまい具合にフックしてくれる。

上で挙げたXMLの書式だが、文章として必要最低限の要素で構成されている。XHTML文章としては全く足りないが、XHTML文章で必要となるmeta要素などの情報はサイト内で使い回しが効くためrsd.xslでXHTMLへ変換する際に付ければ十分である。文章としての情報のみをXMLに記述することで例えば作者のメールアドレスが変わったとしても一括してXSLT側で変更できるので保守性が高まる。HTMLとCSSの関係がXMLとPHP、XSLTの関係にも当てはまると言えるだろう。

関連情報

連絡先、リンク、転載や複製などについては「サイト案内」をご覧ください。Powered by HIMMEL