テンプレートのレイアウトに XInclude を使ってデザイナさんと仲良く

| | コメント(4) | トラックバック(0)

XML Inclusions (XInclude)を使ったテンプレートのレイアウト方法はどうでしょうかというお話。

PHP でテンプレートと言えば生の PHP でぺたっと書くか、Smarty やらといったテンプレートエンジンを利用するのが一般的だと思います。このテンプレート、デザイナさんから見ると嫌な存在ではないでしょうか?テンプレート毎に文法を覚えたり、対応したエディタを用意したり。せっかく覚えるならいろんな言語で通用する技術がいいですよね。XSLT もいいですが、ちょっとひねくれて XInclude を使っちゃいましょう。

ここでは、PHP で XInclude に触れてみたいと思います。まず、デザイナさんに一枚の XHTML を渡します。

Template.xhtml

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

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xmlns:xi="http://www.w3.org/2001/XInclude" xml:lang="ja-JPN">
    <head>
        <!-- この部分にヘッダを書いて下さいネ。 -->
        <!-- <link rel="stylesheet" type="text/css" href="" /> -->
        <!-- <script type="text/javascript" src=""></script> -->

        <xi:include href="Page.xhtml" xpointer="xmlns(xh=http://www.w3.org/1999/xhtml) xpointer(/xh:html/xh:head/*)">
            <xi:fallback>
                <!-- この部分は実行時にページ固有のヘッダに置き換えられます。 -->
                <title>デザイン中です</title>
            </xi:fallback>
        </xi:include>
    </head>
    
    <body>
        <xi:include href="Page.xhtml" xpointer="xmlns(xh=http://www.w3.org/1999/xhtml) xpointer(/xh:html/xh:body/*)">
            <xi:fallback>
                <!-- この部分は実行時にページ固有の本本に置き換えられます。 -->
                <!-- 本本はだいたい次の XHTML となります(CSS 確認用に使って下さいネ)。 -->
                <h1>本文</h1>
                <p>どうたらこうたら</p>
                <h2>概要</h2>
                <p>どんどこどんどん</p>
                <h2>以下略</h2>
                <p>...</p>
            </xi:fallback>
        </xi:include>
    </body>
</html>

XInclude の名前空間に属する要素がある以外、普通の XHTML 1.1 です。ファイルを渡すときにはデザイナさんへ「xi: が付いているタグは絶対に触らぬよう、祟りがあるぞえ」とお願いしましょう。xi:include 要素が動的に作成したい部分です。このファイルの XInclude は、現在のドキュメントの head 要素と body 要素に Page.xhtml の head 要素と body 要素の子要素をそれぞれマージするよう書かれています。xi:fallback には Page.xhtml からマージされる内容の例を記述しておきます。xi:fallback の内容はマージが失敗した場合の代価として使用されます。ですので、デザイナさんがブラウザで単体テストを行った時に本番に近い構造で確認を行えます。最近のまっとうなエディタなら XHTML に対応しているので、問題なくデザインできると思います。

次にプログラマさんのお仕事です。用意する必要があるものは、Template.xhtml を XInclude 処理する PHP スクリプトと、マージされる Page.xhtml ファイルの二つです。

xinclude.php

<?php

// HTTP ヘッダを出力します。
$contentType = preg_match('#(^|,)\\s*application/xhtml\\+xml\\s*(,|;|$)#u', $_SERVER['HTTP_ACCEPT']) ? 'application/xhtml+xml' : 'text/html';
mb_language('uni');
mb_internal_encoding('UTF-8');
$charset = mb_preferred_mime_name(mb_internal_encoding());
header(sprintf('Content-Type: %s; charset=%s', $contentType, $charset));

// テンプレを XInclude 処理して出力します。
$document = new DOMDocument();
$document->load('Template.xhtml', LIBXML_NONET);
$document->xinclude(LIBXML_NONET);
$document->save('php://output');

Page.xhtml

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

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja-JPN">
    <head>
        <link rel="stylesheet" type="text/css" href="document.css" />
    </head>
    <body>
        <h1>ドキュメント</h1>
        <p>ほげほげについて。</p>
        <h2>概要</h2>
        <p>ほげほげである。</p>
        <h2>以下略</h2>
        <p>...</p>
    </body>
</html>

ここまで用意したら、後はデザイナさんがデザインしたテンプレートを待ちます。

デザインされた Template.xhtml

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

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xmlns:xi="http://www.w3.org/2001/XInclude" xml:lang="ja-JPN">
    <head>
        <link rel="stylesheet" type="text/css" href="core.css" />
        <link rel="stylesheet" type="text/css" href="document.css" />
        <script type="text/javascript" src="prototype.js"></script>
        <script type="text/javascript" src="jquery.js"></script>
        
        <xi:include href="Page.xhtml" xpointer="xmlns(xh=http://www.w3.org/1999/xhtml) xpointer(/xh:html/xh:head/*)">
            <xi:fallback>
                <!-- この部分は実行時にページ固有のヘッダに置き換えられます。 -->
                <title>デザイン中です</title>
            </xi:fallback>
        </xi:include>
    </head>
    
    <body>
        <div id="header">
            <img src="logo.png" title="サイトロゴマーク" width="100" height="60" />
            
            <ul class="menu" title="お品書き">
                <li><a href="#">ホーム</a></li>
                <li><a href="#">ドキュメント</a></li>
                <li><a href="#">ダウンロード</a></li>
                <li><a href="#">ヘルプ</a></li>
            </ul>
        </div>

        <div id="body">
            <xi:include href="Page.xhtml" xpointer="xmlns(xh=http://www.w3.org/1999/xhtml) xpointer(/xh:html/xh:body/*)">
                <xi:fallback>
                    <!-- この部分は実行時にページ固有の本本に置き換えられます。 -->
                    <!-- 本本はだいたい次の XHTML となります(CSS 確認用に使って下さいネ)。 -->
                    <h1>本文</h1>
                    <p>どうたらこうたら</p>
                    <h2>概要</h2>
                    <p>どんどこどんどん</p>
                    <h2>以下略</h2>
                    <p>...</p>
                </xi:fallback>
            </xi:include>
        </div>
        
        <div id="footer">
            <p>Copyright 2007 hogehoge</p>
        </div>
    </body>
</html>

こうして出来上がった xinclude.php, Template.xhtml, Page.xhtml を、全て同じディレクトリに放り込んで xinclude.php にアクセスします。

出力結果
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:xi="http://www.w3.org/2001/XInclude" xml:lang="ja-JPN">
    <head>
        <link rel="stylesheet" type="text/css" href="core.css"/>
        <link rel="stylesheet" type="text/css" href="document.css"/>
        <script type="text/javascript" src="prototype.js"/>
        <script type="text/javascript" src="jquery.js"/>
        
        <link xmlns="http://www.w3.org/1999/xhtml" rel="stylesheet" type="text/css" href="document.css"/>

    </head>
    
    <body>
        <div id="header">
            <img src="logo.png" title="サイトロゴマーク" width="100" height="60"/>
            
            <ul class="menu" title="お品書き">
                <li><a href="#">ホーム</a></li>
                <li><a href="#">ドキュメント</a></li>
                <li><a href="#">ダウンロード</a></li>

                <li><a href="#">ヘルプ</a></li>
            </ul>
        </div>

        <div id="body">
            <h1 xmlns="http://www.w3.org/1999/xhtml">ドキュメント</h1><p xmlns="http://www.w3.org/1999/xhtml">ほげほげについて。</p><h2 xmlns="http://www.w3.org/1999/xhtml">概要</h2><p xmlns="http://www.w3.org/1999/xhtml">ほげほげである。</p><h2 xmlns="http://www.w3.org/1999/xhtml">以下略</h2><p xmlns="http://www.w3.org/1999/xhtml">...</p>

        </div>
        
        <div id="footer">
            <p>Copyright 2007 hogehoge</p>
        </div>
    </body>
</html>

無事、テンプレートにデータが取り込まれた形になりました。今回のケースでは、テンプレートがデータに強く結合していて、そのままでは使い物にはなりません。DOM API でインクルード対象を変えたテンプレートを、別に作成しておくとかの小細工が必要です。他の XML ファミリーの技術を利用するのもいいかもです(XSLT 使ったら XInclude がいらない子に…_no)。

PHP DOM 関数ですが、ネット上にある DTD を読み込まないようにしています。DTD を検証しないと外部エンティティの解決とかいろいろ問題がでるのですが、読み込んでるだけでタイムアウトしちゃいます。DOM 関数のベースとなっている libxml2 が「DTD のキャッシュなんて XML Catalog とかに任せとけばいいんじゃないかな?」だそうで、Windows 環境はどうしたらいいのよ、ンモー。

トラックバック(0)

このブログ記事を参照しているブログ一覧: テンプレートのレイアウトに XInclude を使ってデザイナさんと仲良く

このブログ記事に対するトラックバックURL: http://zenith.sakura.ne.jp/mt/mt-tb.cgi/10

コメント(4)

This really is genuinely excellent news. Thank you for sharing it with us!

I found your blog site on google and check several of the early posts. Continue to keep up the good work. I just added up your RSS feed to my MSN News Reader. Looking forward to reading through far more from you later on!

Cheers for this content, guys, continue to keep up the good work.

Here is an area likely to become your help!

コメントする


画像の中に見える文字を入力してください。

このブログ記事について

このページは、zenithが2007年12月26日 21:47に書いたブログ記事です。

ひとつ前のブログ記事は「海王星もそろそろ年末」です。

次のブログ記事は「日本海テレビのジングルが初音ミクっぽい」です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。

Powered by Movable Type 4.12