Kwartzユーザーズガイド
last update: $Date: 2005-03-07 08:15:41 +0900 (Mon, 07 Mar 2005) $
はじめに
このドキュメントは、テンプレートシステムKwartz(*1)のユーザーズガイドです。 Kwartzは、『プレゼンテーションロジックとプレゼンテーションデータの分離(Separation of Presentation Logic and Presentation Data, SoPL/PD)』という概念を実現したテンプレートシステムです。
- (*1)
- Kwartzの開発は、情報処理推進機構(IPA)による平成15年度未踏ソフトウェア創造事業の支援を受けました。
目次
Kwartzについて
Kwartzとは?
Kwartz(*2)とは、 『プレゼンテーションロジックとプレゼンテーションデータの分離(Separation of Presentation Logic and Presentaion Data(SoPL/PD)』という概念を実現したテンプレートシステムです。
Kwartz-rubyは、RubyによるKwartzの実装です。 このほか、PHPやJavaによる実装も予定されています。
以降の説明では、「Kwartz」という言葉はテンプレートシステムの仕様を説明するときに使用し、 「Kwartz-ruby」という言葉は特定の実装について説明するときに使用します。
- (*2)
- Kwartzは'Quartz'と同じように発音してください。
特徴
Kwartzには次のような特徴があります。
- プレゼンテーションデータとプレゼンテーションロジックとが分離可能
-
通常のテンプレートシステムではテンプレートとメインプログラムとを分離します。 Kwartzでは更に、テンプレートをプレゼンテーションデータとプレゼンテーションロジックとに分離します。 これにより、プレゼンテーションロジックがHTMLの中に混じることも、またメインプログラムに紛れ込むこともありません。
- 高速な動作
-
Kwartzでは、テンプレート(プレゼンテーションデータとプレゼンテーションロジック)から出力用スクリプトを生成します。 これをあらかじめ行っておくため、実行時には出力用プログラムを呼び出すだけでよく、極めて高速に動作します。 またDOMツリーのような木構造を使わずに済むため、他のテンプレートシステムよりも高速です。
- 複数のプログラミング言語に対応
-
Kwartzは内部で独自の中間言語を採用することにより、様々なプログラミング言語から使用できるようになっています。 つまり、ひとつのHTMLテンプレートを様々な言語から使用することができるのです。 また使用する言語を変えたとしても、プレゼンテーション層は何も変更する必要がありません。 現在のところ、Ruby(eRuby)、PHP、JSP(JSTL 1.1&1.0)に対応しています。
- HTMLテンプレートがSGML形式を崩さない
-
Kwartzでは、HTMLテンプレートにおけるマーキング(印付け)をid属性で行っています。 そのため、 Smarty や Jakarta Velocity のようにHTMLテンプレートのデザインを崩してしまうことがありません。
- 任意のテキストファイルで使用可能
-
Kwartzでは、専用の属性がついたタグのみを認識し、それ以外のタグはただのプレーンテキストとみなします。 またHTMLパーサーやXMLパーサーを使用せず、独自に解析を行っています。 そのため、Enhydra XMLC や amrita のようにXMLやHTMLでしか使用できないということはなく、任意のテキストファイルで使用可能です。
- 自動サニタイズ機能をサポート
-
Kwartzでは、サニタイズを自動的に行うようにすることができます。 つまり、いちいち「CGI.escapeHTML(var)」や「
htmlspecialchars($var)」と書く必要がありません。 またサニタイズ機能はオン/オフすることができます。 さらに、ある部分だけをサニタイズする/しないを細かく指定できます。
簡単な例
Kwartzは、テンプレートをプレゼンテーションデータとプレゼンテーションロジックとに分けて記述します。 ここではその例を示します。
まずプレゼンテーションデータの例です。
- 「
id="list"」はそのエレメントにvaluesという名前で「目印」をつけること、つまり操作対象とすることを表します。Kwartzでは、エレメントに目印をつけることを「マーキング(Marking)」といいます。 - 同様に、「
id="item"」は<td>エレメントにitemという名前で「目印」をつけています。
プレゼンテーションデータ(example1.html):
<table>
<tr id="list">
<td id="item">foo</td>
</tr>
</table>
次はプレゼンテーションロジックの例です。 プレゼンテーションロジックでは、プレゼンテーションデータにつけた「目印」に対して操作を行います。
- 「
#item { ... }」は目印「item」がつけられたエレメント(Element, ここでは<td>から<t/d>まで)を表します。- 「
value: expression;」は、エレメントの内容を式expressionの値(ここでは変数memberの値)で置き換えることを表します。 - 「
remove: "id";」は、エレメントからid属性を取り除くことを表します。 なお「id="name"」のかわりに「id="mark:name"」を使用するとid属性は自動的に削除され、「remove: "id";」をいちいち記述する必要はなくなります。
- 「
- 「
#list { ... }」は目印「list」がつけられたエレメント(Element, ここでは<tr>から</tr>まで)を表します。- 「
plogic: { ... }」で、そのエレメントのプレゼンテーションロジックを定義します。 - 「
@stag」は開始タグ(Start tag, ここでは<tr>)を表します。 - 「
@cont」は内容(Content, ここでは<td id="item">foo</td>)を表します。 - 「
@etag」は終了タグ(End tag, ここでは</tr>)を表します。 - 「
foreach (member in member_list) { ... }」は繰り返しを表します。
- 「
プレゼンテーションロジック(example1.plogic):
#item { // id="item" がついたエレメント
value: member; // 内容を変数memberの値で置き換える
remove: "id"; // id属性を取り除く
}
#list { // id="list" がついたエレメント
remove: "id"; // id属性を取り除く
plogic: { // プレゼンテーションロジックを定義する
foreach (member in member_list) {
@stag; // タグ(start tag)
@cont; // 内容(content)
@etag; // 終了タグ(end tag)
}
}
}
Kwartzはこの2つから各言語(eRuby, PHP, JSTL1.1&1.0)用の出力用スクリプトを自動生成します。 これをコンパイルといいます。 コンパイルするにはコマンドラインで次のようにします。
### for eRuby $ kwartz -l eruby -p example1.plogic example1.html > example1.rhtml ### for PHP $ kwartz -l php -p example1.plogic example1.html > example1.php ### for JSTL 1.1 $ kwartz -l jstl11 -p example1.plogic example1.html > example1.jsp ### for JSTL 1.0 $ kwartz -l jstl10 -p example1.plogic example1.html > example1.jsp
以下は自動生成された出力用スクリプトです。
出力用スクリプト for eRuby (example1.rhtml):
<table>
<% for member in member_list do %>
<tr>
<td><%= member %></td>
</tr>
<% end %>
</table>
出力用スクリプト for PHP (example1.php):
<table>
<?php foreach ($member_list as $member) { ?>
<tr>
<td><?php echo $member; ?></td>
</tr>
<?php } ?>
</table>
出力用スクリプト for JSTL 1.1(*3)(example1.jsp):
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<table>
<c:forEach var="member" items="${member_list}">
<tr>
<td><c:out value="${member}" escapeXml="false"/></td>
</tr>
</c:forEach>
</table>
出力用スクリプト for JSTL 1.0(example1.jsp):
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>
<table>
<c:forEach var="member" items="${member_list}">
<tr>
<td><c:out value="${member}" escapeXml="false"/></td>
</tr>
</c:forEach>
</table>
またコンパイル時にコマンドオプション -e をつけると、サニタイズされた出力用スクリプトが生成されます。
サニタイズには、eRubyではCGI.escapeHTML()が、PHPではhtmlspecialchars()が、JSTLではescapeXml="false"なしの<c:out/>が使用されます。
これらの出力用スクリプトをメインプログラムから呼び出すと、Webページが出力されます。 呼び出し方は、各プログラミング言語によって異なります。
メインプログラム(Ruby):
## データを用意する
member_list = [ 'Oboro', 'Ominae', 'Jaquemonde' ]
## ERBを使って出力する
require 'erb'
require 'cgi' # for sanitizing
str = File.open('example1.rhtml') { |f| f.read() }
str.untaint
trim_mode = 1
erb = ERB.new(str, $SAFE, trim_mode)
print erb.result(binding())
## またはERubyを使う方法
require 'eruby'
require 'cgi' # for sanitizing
ERuby::import('example1.rhtml')
メインプログラム(PHP):
<?php
// データを用意する
$member_list = array('Oboro', 'Ominae', 'Jaquemonde');
// 出力する
include('example1.php');
?>
メインプログラム(JSTL):
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
...
// データを用意する
java.util.List member_list = new java.util.ArrayList();
member_list.add("Oboro");
member_list.add("Ominae");
member_list.add("Jaquemonde");
// 出力
RequestDispatcher dispatcher =
request.getRequestDispatcher('example1.jsp');
dispatcher.include(request, response);
// または dispatcher.forward(request, response);
}
出力用プログラムを呼び出して実行すると、例えば次のようなWebページが生成されます。
<table>
<tr>
<td>Oboro</td>
</tr>
<tr>
<td>Ominae</td>
</tr>
<tr>
<td>Jaquemonde</td>
</tr>
</table>
- (*3)
- コマンドラインオプションとして「--charset=CHARSET」をつけると、JSTL用出力スクリプトでは「
<%@ page contentType="text/html; charset=CHARSET" %>」をつけてくれます。
複雑な例
もう少し複雑な例として、色つきのテーブルを示します。
プレゼンテーションデータは次のようになります。
マーキングは「id="name"」ではなく「id="mark:name"」としています。
こうするとid属性は自動的に削除されますので、プレゼンテーションロジックファイルでいちいち「remove: "id"」と書く必要がなくなります。
プレゼンテーションデータ(example2.html):
<table> <tr bgcolor="#CCCCFF" id="mark:list"> <td id="mark:name">foo</td> <td> <a href="mailto:foo@mail.com" id="mark:email">foo@mail.com</a> </td> </tr> </table>
次はプレゼンテーションロジックです。 プレゼンテーションロジックでは、繰り返しを行いながら、奇数行か偶数行かの判定を行っています。
プレゼンテーションロジック(example2.plogic):
// id="mark:list" がついたエレメント:
// bgcolor属性の値として変数colorを出力する。
// また繰り返しを行い、奇数行と偶数行で変数colorの値を変える。
#list {
attr: "bgcolor" color;
plogic: {
i = 0;
foreach (member in member_list) {
i += 1;
color = i % 2 == 0 ? '#FFCCCC' : '#CCCCFF';
@stag;
@cont;
@etag;
}
}
}
// id="mark:name" がついたエレメント:
// 内容として member['name'] の値を出力する。
#name {
value: member['name'];
}
// id="mark:email" がついたエレメント:
// 内容として member['email'] の値を出力する。
// またhref属性は "mailto:" .+ member['email'] の値を出力する。
// (「.+」は文字列の連結を行う演算子)
#email {
value: member['email'];
attr: "href" ("mailto:" .+ member['email']);
}
見ておわかりのように、プレゼンテーションロジックにはHTMLタグが一切入らず、またプレゼンテーションデータにはロジックが一切入っていません。 つまり、プレゼンテーションデータとプレゼンテーションロジックの分離が実現できていることになります。
なおインクリメント演算子(++)は使えませんので、ctr++ のように書くことはできません。
コンパイル:
### for eRuby $ kwartz -l eruby -p example2.plogic example2.html > example2.rhtml ### for PHP $ kwartz -l php -p example2.plogic example2.html > example2.php ### for JSTL 1.1 $ kwartz -l jstl11 -p example2.plogic example2.html > example2.jsp ### for JSTL 1.0 $ kwartz -l jstl10 -p example2.plogic example2.html > example2.jsp
出力用スクリプト:
### for eRuby
<table>
<% i = 0 %>
<% for member in member_list do %>
<% i += 1 %>
<% color = i % 2 == 0 ? "#FFCCCC" : "#CCCCFF" %>
<tr bgcolor="<%= color %>">
<td><%= member["name"] %></td>
<td>
<a href="<%= "mailto:" + member["email"] %>"><%= member["email"] %></a>
</td>
</tr>
<% end %>
</table>
### for PHP
<table>
<?php $i = 0; ?>
<?php foreach ($member_list as $member) { ?>
<?php $i += 1; ?>
<?php $color = $i % 2 == 0 ? "#FFCCCC" : "#CCCCFF"; ?>
<tr bgcolor="<?php echo $color; ?>">
<td><?php echo $member["name"]; ?></td>
<td>
<a href="<?php echo "mailto:" . $member["email"]; ?>"><?php echo $member["email"]; ?></a>
</td>
</tr>
<?php } ?>
</table>
### for JSTL
<table>
<c:set var="i" value="0"/>
<c:forEach var="member" items="${member_list}">
<c:set var="i" value="${i + 1}"/>
<c:set var="color" value="${i % 2 eq 0 ? '#FFCCCC' : '#CCCCFF'}"/>
<tr bgcolor="<c:out value="${color}" escapeXml="false"/>">
<td><c:out value="${member['name']}" escapeXml="false"/></td>
<td>
<a href="<c:out value="${fn:join('mailto:',member['email'])}" escapeXml="false"/>"><c:out value="${member['email']}" escapeXml="false"/></a>
</td>
</tr>
</c:forEach>
</table>
プレゼンテーションロジックの応用例
Kwartzでは、複雑なプレゼンテーションロジックが素直に記述できます。 ここではその例を示します。 なお『プレゼンテーションパターンカタログ』もご覧ください。
- エレメント全体を繰り返すことができます。
#list { plogic: { foreach (member in member_list) { @stag; @cont; @etag; } } }
- 内容だけを繰り返すことができます。<dl></dl>で使うのに向いています。
#list { plogic: { @stag; foreach (member in member_list) { @cont; } @etag; } }
- 内容のかわりに、変数や式などの値を出力することができます。
#list { plogic: { @stag; print("Hello!"); @etag; } }これは次と同じです。#list { value: "Hello!"; }
- エレメントのかわりに、変数や式などの値を出力することができます。
#list { plogic: { print("<b>Hello!</b>"); } }
- 内容だけを残し、開始タグと終了タグを消すことができます。
#list { plogic: { @cont; } }
- エレメント全体を消すことができます。これは、ダミーデータを消すときに便利です。
#list { plogic: { } }
- エレメント全体を、別のエレメントで置き換えることができます。
#list { plogic: { @element(foo); // 「foo」とマーキングされたエレメントを展開する } }
- エレメントの内容を、別のエレメントで置き換えることができます。
#list { plogic: { @stag; @element(foo); // 「foo」とマーキングされたエレメントを展開する @etag; } }
- 複雑なプレゼンテーションロジックを含めることができます。
#list { plogic: { i = 0; foreach (member in member_list) { i += 1; // 注意:i++ や ++i は使えません if (i % 2 == 0) { color = 'red'; } else { color = 'blue'; } @stag; @cont; @etag; } }
ここで重要なのは、プレゼンテーションロジックにはタグ名や属性名が一切出てきていないという点です。 プレゼンテーションデータのほうでどんなにタグを変更したとしても、プレゼンテーションロジックはまったく変更する必要はありません。
つまり、プレゼンテーションデータとプレゼンテーションロジックとが完全に分離されているわけです。
ディレクティブ
Kwartzでは、プレゼンテーションデータの中にプレゼンテーションロジックを埋め込むこともできます。 つまり、両者を分離することも、一体化することもできるわけです。
プレゼンテーションロジックをプレゼンテーションデータの中に埋め込むには、ディレクティブを用います。 ディレクティブとは、プレゼンテーションデータの中にプレゼンテーションロジックを埋め込むための命令です。 Kwartzでは、id属性とkw:d属性を用いてディレクティブを記述します。
次はディレクティブを使った例です:
- 「
id="foreach:var=list"」は、繰り返しを表します。 - 「
id="value:expression"」は、内容のかわりに式の値を出力することを表します。 - 「
id="dummy:str"」は、そのエレメントがダミーであることを表します(つまり出力されません)。 ここでstrはid属性の値が同じにならないようにするためのものであり、特に意味はありません。 - 「
@{expression}@」(*4)は、式の値を出力するためのディレクティブです。
プレゼンテーションデータ(example3.html):
<table>
<tr id="foreach:member=member_list">
<td id="value:member['name']">foo</td>
<td><a href="mailto:@{member['email']}@">
@{member['email']}@</a></td>
</tr>
<tr id="dummy:d1">
<td>bar</td>
<td><a href="mailto:bar@mail.org">bar@mail.org</a></td>
</tr>
<tr id="dummy:d2">
<td>baz</td>
<td><a href="mailto:baz@mail.net">baz@mail.net</a></td>
</tr>
</table>
コンパイル:
### for eRuby $ kwartz -l eruby example3.html > example3.rhtml ### for PHP $ kwartz -l php example3.html > example3.php ### for JSTL1.1 $ kwartz -l jstl11 example3.html > example3.jsp
出力用スクリプト:
### for eRuby
<table>
<% for member in member_list do %>
<tr>
<td><%= member["name"] %></td>
<td><a href="mailto:<%= member["email"] %>">
<%= member["email"] %></a></td>
</tr>
<% end %>
</table>
### for PHP
<table>
<?php foreach ($member_list as $member) { ?>
<tr>
<td><?php echo $member["name"]; ?></td>
<td><a href="mailto:<?php echo $member["email"]; ?>">
<?php echo $member["email"]; ?></a></td>
</tr>
<?php } ?>
</table>
### for JSTL
<table>
<c:forEach var="member" items="${member_list}">
<tr>
<td><c:out value="${member['name']}" escapeXml="false"/></td>
<td><a href="mailto:<c:out value="${member['email']}" escapeXml="false"/>">
<c:out value="${member['email']}" escapeXml="false"/></a></td>
</tr>
</c:forEach>
</table>
このほか、条件分岐を行うディレクティブなども用意されています。 詳細はリファレンスマニュアルをご覧ください。
- (*4)
- このパターンは設定ファイルの定数EMBED_PATTERNで変更できます。
サニタイズ
Kwartzでは、自動でサニタイズを行うことができます。 またある部分だけをサニタイズする/しないを選択することもできます。
自動サニタイズ
コマンドラインオプション -e をつけると、出力スクリプトをサニタイズします。
サニタイズでは、eRubyではCGI.escapeHTML()が、ERBではh()が、PHPではhtmlspecialchars()が、JSTLではescapeXml="false"なしの<c:out>がそれぞれ使用されます。
プレゼンテーションデータ:
<tr bgcolor="@{color}@">
<td id="value:str">foo</td>
</tr>
コンパイル:
### for eRuby $ kwartz -e -l eruby sanitize1.html > sanitize1.rhtml ### for ERB $ kwartz -e -l erb sanitize1.html > sanitize1.rhtml ### for PHP $ kwartz -e -l php sanitize1.html > sanitize1.php ### for JSTL 1.1 $ kwartz -e -l jstl11 sanitize1.html > sanitize1.jsp
出力用スクリプト:
### for eRuby
<tr bgcolor="<%= CGI::escapeHTML((color).to_s) %>">
<td><%= CGI::escapeHTML((str).to_s) %></td>
</tr>
### for ERB
<tr bgcolor="<%=h(color)%>">
<td><%=h(str)%></td>
</tr>
### for PHP
<tr bgcolor="<?php echo htmlspecialchars($color); ?>">
<td><?php echo htmlspecialchars($str); ?></td>
</tr>
### for JSTL
<tr bgcolor="<c:out value="${color}"/>">
<td><c:out value="${str}"/></td>
</tr>
式が文字列や数値のような定数の場合は、サニタイズされません。
また「flag ? 'checked' : ''」のような条件演算子では、flagの値にかかわらず文字列定数が出力されますので、これもサニタイズされません。
部分サニタイズ
関数E(expr)は、コマンドラインオプションに関わらず式exprをサニタイズします。
また関数X(expr)は、コマンドラインオプションに関わらず式exprをサニタイズしません。
プレゼンテーションデータ:
<table>
<tr bgcolor="@{X(color)}@">
<td id="value:E(str)">foo</td>
</tr>
</table>
コンパイル:
### for eRuby $ kwartz -e -l eruby sanitize1.html > sanitize1.rhtml ### for ERB $ kwartz -e -l erb sanitize1.html > sanitize1.rhtml ### for PHP $ kwartz -e -l php sanitize1.html > sanitize1.php ### for JSTL 1.1 $ kwartz -e -l jstl11 sanitize1.html > sanitize1.jsp
出力用スクリプト:
### for eRuby
<table>
<tr bgcolor="<%= color %>">
<td><%= CGI::escapeHTML((str).to_s) %></td>
</tr>
</table>
### for ERB
<table>
<tr bgcolor="<%= color %>">
<td><%=h(str)%></td>
</tr>
</table>
### for PHP
<table>
<tr bgcolor="<?php echo $color; ?>">
<td><?php echo htmlspecialchars($str); ?></td>
</tr>
</table>
### for JSTL
<table>
<tr bgcolor="<c:out value="${color}" escapeXml="false"/>">
<td><c:out value="${str}"/></td>
</tr>
</table>
またコマンドラインオプションに関係なく、「id="Value:expr"」や「id="Attr:name=expr)"」は式exprを必ずサニタイズします。
逆に、「id="VALUE:expr"」や「id="ATTR:name=expr"」は式exprを必ずサニタイズしません。
これらはそれぞれ、「id="value:E(expr)"」や「id="attr:name=X(expr)"」と同じです。
サニタイズの設定
kwartz/config.rbはKwartz-rubyの動作を設定しているファイルです。
デフォルトでサニタイズを行うように設定するには、この中で定数ESCAPEの値をtrueに変更します。
その他の話題
制限事項
Kwartzでは、HTMLパーサやXMLパーサを用いず、正規表現によるパターンマッチでHTMLファイルを解析しています。 そのため、HTMLではないテキストファイルでも利用できるという利点がありますが、次のような制限事項もあります。
- id属性がついたタグは、終了タグを省略できません。
<!-- </li> が指定されていないので解析できない --> <ul> <li id="foo">foo </ul>
また内容を持たない場合は、<foo id="..."/>のような空タグとしてください。
- ただし、
<input>と<br>と<meta>と<img>と<hr>は、終了タグを省略できます。 また空タグにする必要もありません。<!-- </input> が省略されているが、正しく解析される --> <input type="text" name="user" id="user">
なおこれらのタグ名はkwartz/config.rbの中で定数NOENDに設定されています。 また大文字と小文字は区別されます。
- 属性値は必ず「
"」で囲ってください。また「'」で囲っても認識されません。<!-- 属性値が「"」で囲まれていないので、解析できない --> <h1 id="value:title" class=title>title</h1>
グローバル変数とローカル変数
Kwartzには、プレゼンテーションデータ/ロジックファイルを分析し、変数を調査する機能があります。
Kwartzでは、メインプログラムで設定されて出力用スクリプトに渡される変数をグローバル変数、 テンプレートの中でだけ使用される変数をローカル変数と呼んでいます。 Kwartzは、変数がグローバルかローカルかを調べて報告する機能があります。
次の例をご覧ください。
プレゼンテーションデータ(analyze.html):
<span kw:d="value:title">Analyzer Example</span> <dl id="mark:items"> <dt kw:d="value:ctr"></dt> <dd kw:d="value:item">Foo</dd> </dl>
プレゼンテーションロジック(analyze.plogic):
#items {
plogic: {
@stag;
ctr = 0;
foreach (item in list) {
ctr += 1;
@cont;
}
@etag;
}
}
この例では4つの変数があります。
このうち、itemとctrはテンプレート中でだけ使われるのでローカル変数、
titleとlistはメインプログラムで設定されて出力用スクリプトに渡されるのでグローバル変数です。
kwartzをコマンドランオプション -a analyze をつけて起動すると、グローバル変数とローカル変数を報告してくれます。
実行例:
$ kwartz -a analyze -p analyze.plogic analyze.html Global: title list Local: ctr item
ローカル変数の名前を変更する
RubyやPHPでは、メインプログラムで使用している変数名と、テンプレートのローカル変数名とが一致した場合、 ローカル変数名を変更することでメインプログラムの動作に影響を与えてしまうという問題があります。 これに対処するため、Kwartzではローカル変数名を自動的に変更する機能があります。
コンパイル時にコマンドラインオプション「--rename」を指定すると、
ローカル変数名の頭に「_をつけます。
前の節で使用したanalyze.htmlとanalyze.plogicを使ってみます。
実行例:
$ kwartz -l eruby -p analyze.plogic --rename analyze.html $ kwartz -l php -p analyze.plogic --rename analyze.html $ kwartz -l jstl11 -p analyze.plogic --rename analyze.html
出力用スクリプト:
### for eRuby
<%= title %>
<dl>
<% _ctr = 0 %>
<% for _item in list do %>
<% _ctr += 1 %>
<dt><%= _ctr %></dt>
<dd><%= _item %></dd>
<% end %>
</dl>
### for PHP
<?php echo $title; ?>
<dl>
<?php $_ctr = 0; ?>
<?php foreach ($list as $_item) { ?>
<?php $_ctr += 1; ?>
<dt><?php echo $_ctr; ?></dt>
<dd><?php echo $_item; ?></dd>
<?php } ?>
</dl>
### for JSTL
<c:out value="${title}" escapeXml="false"/>
<dl>
<c:set var="_ctr" value="0"/>
<c:forEach var="_item" items="${list}">
<c:set var="_ctr" value="${_ctr + 1}"/>
<dt><c:out value="${_ctr}" escapeXml="false"/></dt>
<dd><c:out value="${_item}" escapeXml="false"/></dd>
</c:forEach>
</dl>
なお設定ファイルの定数RENAMEで、デフォルトでローカル変数名を変更する・しないを設定できます。
spanタグの削除
Kwartzでは、ディレクティブしか含まないようなspanタグは、ダミータグとみなされて自動的に削除されます。
プレゼンテーションデータ:
<h1><span id="mark:title">title</span></h1> Hello <span id="value:user">World</span>!
プレゼンテーションロジック:
#title {
value: title;
}
出力用スクリプト(for eRuby):
<h1><%= title %></h1> Hello <%= user %>!
spanタグが他の属性を含んでいた場合は、削除されません。
プレゼンテーションデータ:
<h1><span id="mark:title" class="title">title</span></h1> Hello <span kw:d="value:user" style="color:black">World</span>!
出力用スクリプト(for eRuby):
<h1><span class="title"><%= title %></span></h1> Hello <span style="color:black"><%= user %></span>!
開始タグに式の値を追加する
「<input type="..." checked>」のようにする場合は、次のようにします。
プレゼンテーションデータ:
<input type="checkbox" name="foo" value="Y" id="foo" />
プレゼンテーションロジック:
#foo {
append: flag ? ' checked' : '';
}
出力用スクリプト:
### for eRuby
<input type="checkbox" name="foo" value="Y" id="foo"<%= flag ? " checked" : "" %> />
### for PHP
<input type="checkbox" name="foo" value="Y" id="foo"<?php echo $flag ? " checked" : ""; ?> />
### for JSTL 1.1
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<input type="checkbox" name="foo" value="Y" id="foo"<c:out value="${flag ? ' checked' : ''}" escapeXml="false"/> />
### for JSTL 1.0
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>
<c:choose><c:when test="${flag}">
<input type="checkbox" name="foo" value="Y" id="foo" checked />
</c:when><c:otherwise>
<input type="checkbox" name="foo" value="Y" id="foo" />
</c:otherwise></c:choose>
ディレクティブ id="append:expr" でも同じことができます。
プレゼンテーションデータ:
<input type="checkbox" name="foo" value="Y" id="append:flag?' checked':''" />
またchecked="checked"やselected="selected"を簡単に出力するための関数を用意しています。
「C(expr)」「S(expr)」「D(expr)」は式exprが真だった場合に、
それぞれ「 checked="checked"」「 selected="selected"」「 disabled="disabled"」を出力します。
プレゼンテーションデータ:
<input type="checkbox" name="foo" value="Y" id="foo" />
プレゼンテーションロジック:
#foo {
append: C(foo == 100);
}
出力用スクリプト:
### for eRuby
<input type="checkbox" name="foo" value="Y" id="foo"<%= foo == 100 ? " checked=\"checked\"" : "" %> />
### for PHP
<input type="checkbox" name="foo" value="Y" id="foo"<?php echo $foo == 100 ? " checked=\"checked\"" : ""; ?> />
### for JSTL 1.1
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<input type="checkbox" name="foo" value="Y" id="foo"<c:out value="${foo eq 100 ? ' checked="checked"' : ''}" escapeXml="false"/> />
### for JSTL 1.0
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>
<c:choose><c:when test="${foo eq 100}">
<input type="checkbox" name="foo" value="Y" id="foo" checked="checked" />
</c:when><c:otherwise>
<input type="checkbox" name="foo" value="Y" id="foo" />
</c:otherwise></c:choose>
プレゼンテーションロジックをターゲット言語で記述する
行が「<%」または「<?」で始まる場合、そこから行末まではそのまま出力されます。
これにより、プレゼンテーションロジックをRubyやPHPやJavaで直接記述することができます。
プレゼンテーションロジック:
#list {
plogic: {
@stag;
<% ENV.each { |name, value| %>
@cont;
<% } %>
@etag;
}
}
「<%」または「<?」から行末までをraw-codeといいます。
raw-codeは文(statement)であり、式(expression)ではありません。
そのため、「plogic:」部に書くことはできますが「value:」部や「attr:」部に書くことはできません。