<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <meta http-equiv="Content-Script-Type" content="text/javascript" />
    <meta http-equiv="Content-Style-Type" content="text/css" />
    <title>ZPTテンプレート</title>
    <link rel="stylesheet" href="/css/style.css" type="text/css" media="all" />
    
    
  </head>
  <body>
    <div class="header">
      <div id="pane.left-header" class="pane left">
        <div id="org.seasar.kvasir.cms.toolbox.customPop-2" class="pop org.seasar.kvasir.cms.toolbox.customPop">
          <div class="body"><div class="wiki">
<ul>
<li><a href="/" class="pageNotFound">（サイトトップ）</a></li>
<li><a href="/download">ダウンロード</a></li>
<li><a href="/news/" class="pageNotFound">新着情報</a></li>
<li><a href="/docs/" class="pageNotFound">ドキュメント</a></li>
</ul>
</div>
</div>
        </div>
      </div>
      <div id="pane.right-header" class="pane right">
        <div id="org.seasar.kvasir.cms.toolbox.loginPop-1" class="pop org.seasar.kvasir.cms.toolbox.loginPop">
          <div class="body">
<form method="post" action="/plugins/toolbox/login.do/docs/0.9.x/ref/zptTemplate">
    <div class="row">
      <span class="label">Name</span>
      <span class="textinput"><input type="text" name="name" size="12" value="" /></span>
    </div>
    <div class="row">
      <span class="label">Password</span>
      <span class="textinput"><input type="password" name="password" size="12" value="" /></span>
    </div>
    <div class="row">
      <span class="submit"><input type="submit" value="Login" /></span>
    </div>
</form>
</div>
        </div><div id="org.seasar.kvasir.cms.pop.loginUserPop-1" class="pop org.seasar.kvasir.cms.pop.loginUserPop">
          <div class="body"></div>
        </div>
      </div>
    </div>
    <div class="page-frame">
      <div id="pane.left-sidebar" class="pane sidebar-frame sidebar subcontent">
        <div id="org.seasar.kvasir.cms.toolbox.searchPop-1" class="pop org.seasar.kvasir.cms.toolbox.searchPop">
          <h2 class="title">Search</h2>
          <div class="body"><form class="simple" method="get" action="/plugins/toolbox/search.do">
  <input type="text" name="query" size="12" />
  <input type="submit" value="Go!" />
</form>
</div>
        </div><div id="org.seasar.kvasir.cms.toolbox.customPop-1" class="pop org.seasar.kvasir.cms.toolbox.customPop">
          <h2 class="title">メニュー</h2>
          <div class="body"><ul>
  <li><a href="/" class="pageNotFound">（サイトトップ）</a></li>
  <li><a href="/download">ダウンロード</a></li>
  <li><a href="/news">新着情報</a></li>
  
    
    
      <li>
        <a href="/docs/1.0.x">ドキュメント（1.0.x系）</a>
        
      </li><li>
        <a href="/docs/0.9.x">ドキュメント（0.9.x系）</a>
        
      </li>
    
  
  <li><a href="/roadmap">ロードマップ</a></li>
  <li><a href="https://www.seasar.org/issues/browse/YMIR">既知の不具合を閲覧する・不具合を報告する</a></li>
  <li><a href="https://www.seasar.org/svn/ymir/">SVNリポジトリ</a></li>
  <li><a href="http://svn.seasar.org/browse/?root=ymir">SVNリポジトリを閲覧</a></li>
</ul>
</div>
        </div>
      </div>
      <div id="pane.main" class="pane main">
      
        <div id="org.seasar.kvasir.cms.toolbox.breadcrumbsPop-1" class="pop org.seasar.kvasir.cms.toolbox.breadcrumbsPop">
          
          <div class="body"><ul>
  <li class="first"><a href="/">(TOP)</a></li><li><a href="/docs">ドキュメント</a></li><li><a href="/docs/0.9.x">ドキュメント（0.9.x系）</a></li><li><a href="/docs/0.9.x/ref">リファレンスマニュアル</a></li><li>ZPTテンプレート</li>
</ul>
</div>
        </div><div id="org.seasar.kvasir.cms.pop.contentPop-1" class="pop org.seasar.kvasir.cms.pop.contentPop">
          <h2 class="title">ZPTテンプレート</h2>
          <div class="body">
<ul class="information">
  
  <li>2008-07-17 14:43:56</li>
</ul>
<div class="content"><div class="document">
<p>Ymirでの標準のビューテンプレート記述言語はZPT（Zope Page Template）です。ZPTエンジンとしてSkirnirプロジェクトから公開されているタグベーステンプレートエンジン構築フレームワークFreyja（フレイヤ）に含まれているZPT実装（以下単にFreyjaと呼びます）を使っています。</p>
<p>Freyjaは基本的にオリジナルのZPTの仕様に従っていますが、いくつかの違いがあります。ここでは、主にオリジナルの仕様との相違点について説明します。</p>
<p>オリジナルのZPT仕様の詳細については<a class="reference" href="http://wiki.zope.org/ZPT/FrontPage">ZPTのサイト</a>にある</p>
<ul>
<li><a class="reference" href="http://wiki.zope.org/ZPT/TALSpecification14">TAL Specification 1.4</a></li>
<li><a class="reference" href="http://wiki.zope.org/ZPT/TALESSpecification13">TALES Specification 1.3</a></li>
<li><a class="reference" href="http://wiki.zope.org/ZPT/MetalSpecification11">METAL Specification 1.1</a></li>
</ul>
<p>を参照して下さい。</p>
<div class="section" id="e382aae383aae382b8e3838ae383abe381a8e381aee79bb8e98195e782b9">
<h3><a name="e382aae383aae382b8e3838ae383abe381a8e381aee79bb8e98195e782b9">オリジナルとの相違点</a></h3>
<div class="section" id="zpte585a8e888ac">
<h4><a name="zpte585a8e888ac">ZPT全般</a></h4>
<ul>
<li>式の評価結果の真偽判定においては、以下のいずれかに合致した場合に偽とみなします。それ以外は真とみなします。<ul>
<li>評価対象が変数であるが値が存在しない</li>
<li>nullである</li>
<li>java.lang.BooleanインスタンスでかつFALSEと同値である</li>
<li>java.lang.Numberインスタンスでかつ値が0である</li>
<li>配列でかつ長さが0である</li>
<li>java.util.Collectionインスタンスでかつ空である</li>
<li>java.util.Enumerationインスタンスでかつ残りの要素がない</li>
<li>java.util.Iteratorインスタンスでかつ残りの要素がない</li>
<li>toString()の値の長さが0である</li>
</ul>
</li>
</ul>
</div>
<div class="section" id="tal">
<h4><a name="tal">TAL</a></h4>
<ul>
<li>名前空間はサポートしていません。指定しても無視されます。</li>
<li>tal:on-errorで利用できるエラーオブジェクトが異なります。Freyjaでは以下のオブジェクトが利用可能です。<table class="docinfo" frame="void" rules="none">
<col class="docinfo-name" />
<col class="docinfo-content" />
<tbody valign="top">
<tr class="field">
<th class="docinfo-name">type:</th>
<td class="field-body">発生したjava.lang.Throwableのクラス名</td>
</tr>
<tr class="field">
<th class="docinfo-name">value:</th>
<td class="field-body">発生したjava.lang.Throwableオブジェクト</td>
</tr>
<tr class="field">
<th class="docinfo-name">traceback:</th>
<td class="field-body">スタックトレース文字列</td>
</tr>
</tbody>
</table>
</li>
<li><em>[Freyja拡張]</em> tal:contentで空文字列を式として与えた場合は偽と評価されます。</li>
<li>tal:repeatでは、式の評価結果が配列またはjava.util.Collectionである場合はそれらの持つ要素について処理が繰り返されます。nullまたは値が存在しない場合は一度も繰り返されません。それ以外の場合は評価結果自身について一度だけ処理が行なわれます。</li>
<li>tal:repeatで繰り返し変数のプロパティ「Letter」は「LETTER」と表記する必要があります。また、以下のプロパティは未サポートです。<ul>
<li>roman</li>
<li>Roman</li>
</ul>
</li>
</ul>
</div>
<div class="section" id="tales">
<h4><a name="tales">TALES</a></h4>
<ul>
<li>
<p>次の変数が組み込み変数として用意されています。</p>
<table border="1" class="docutils">
<colgroup>
<col width="15%" />
<col width="85%" />
</colgroup>
<thead valign="bottom">
<tr>
<th>名前</th>
<th>値</th>
</tr>
</thead>
<tbody valign="top">
<tr>
<td>nothing</td>
<td>null</td>
</tr>
<tr>
<td>null</td>
<td>null</td>
</tr>
<tr>
<td>default</td>
<td>net.skirnir.freyja.zpt.DefaultクラスのSingletonオブジェクト</td>
</tr>
<tr>
<td>CONTEXTS</td>
<td>グローバル変数が格納されたjava.util.Mapオブジェクト</td>
</tr>
<tr>
<td>true</td>
<td>java.lang.Boolean.TRUE</td>
</tr>
<tr>
<td>false</td>
<td>java.lang.Boolean.FALSE</td>
</tr>
<tr>
<td>request</td>
<td>javax.servlet.http.HttpServletRequestオブジェクト</td>
</tr>
<tr>
<td>response</td>
<td>javax.servlet.http.HttpServletResponseオブジェクト</td>
</tr>
<tr>
<td>session</td>
<td>javax.servlet.http.HttpSessionオブジェクト。セッションが生成されていない場合は未定義</td>
</tr>
<tr>
<td>application</td>
<td>javax.servlet.ServletContextオブジェクト</td>
</tr>
<tr>
<td>locale</td>
<td>リクエストを処理する際のLocaleオブジェクト</td>
</tr>
<tr>
<td>ymirRequest</td>
<td><em>[Ymir拡張]</em> org.seasar.ymir.Requestオブジェクト</td>
</tr>
<tr>
<td>container</td>
<td><em>[Ymir拡張]</em> org.seasar.framework.container.S2Containerオブジェクト</td>
</tr>
<tr>
<td>messages</td>
<td><em>[Ymir拡張]</em> メッセージリソースが格納されているorg.seasar.ymir.Messagesオブジェクト</td>
</tr>
<tr>
<td>token</td>
<td><em>[Ymir拡張]</em> トランザクショントークンを扱うためのorg.seasar.ymir.Tokenオブジェクト。詳しい使い方については「<a class="reference" href="/doc/ref/transactionToken">トランザクショントークン</a>」を参照のこと</td>
</tr>
</tbody>
</table>
<p>また変数ではありませんが負でない整数を書いた場合、その数値を表すjava.lang.Integerのオブジェクトとみなされます。</p>
<p>以下の変数は未サポートです。</p>
<ul>
<li>options</li>
<li>attrs</li>
<li>root</li>
<li>here</li>
<li>container</li>
<li>template</li>
<li>user</li>
<li>modules</li>
</ul>
</li>
<li><em>[Freyja拡張]</em> 複数のセグメントからなるPath式を評価する時、セグメントの評価値が偽である場合は次のセグメントを評価しますが、セグメントの区切り記号として「<tt class="docutils literal"><span class="pre">||</span></tt>」を使用すると、セグメントの評価値がnullのときのみ次のセグメントを評価します。</li>
<li>Nocall式は式の値を加工しません。「<tt class="docutils literal"><span class="pre">nocall:</span></tt>」をつけない場合と同じ挙動をします。</li>
<li>Python式はサポートしていません。</li>
<li><em>[Freyja拡張]</em> Java式をサポートしています。具体的には、「<tt class="docutils literal"><span class="pre">java:</span></tt>」をつけることでJavaの式を記述することができます（Tigerの記法には対応していません）。</li>
<li><em>[Freyja拡張]</em> Page式をサポートしています。「<tt class="docutils literal"><span class="pre">page:&lt;コンテキストパス相対のURI&gt;</span></tt>」という式を、URIにコンテキストパスを補完して必要に応じてセッションIDを付加したURLに変換します。URIにはリクエストパラメータを付与することもできます。また、URIの途中やリクエストパラメータの中にString式のような$...という置換指定を記述することもできます。リクエストパラメータの中に記述された置換指定は、値をURLエンコードした上で埋め込まれます。</li>
<li><em>[Freyja拡張]</em> Include式をサポートしています。「<tt class="docutils literal"><span class="pre">include:&lt;コンテキストパス相対のURI&gt;</span></tt>」という式を、指定されたURIが指すページの内容に置き換えます。これはJSPの<tt class="docutils literal"><span class="pre">&lt;jsp:include&gt;</span></tt>に相当します。</li>
<li><em>[Freyja拡張]</em> IncludeBody式をサポートしています。「<tt class="docutils literal"><span class="pre">include-body:&lt;コンテキストパス相対のURI&gt;</span></tt>」という式を、指定されたURIが指すページの&lt;body&gt;タグの内容（&lt;body&gt;タグ自身は含みません）に置き換えます。</li>
<li><em>[Freyja拡張]</em> I18npage式をサポートしています。「<tt class="docutils literal"><span class="pre">i18npage:&lt;コンテキストパス相対のURI&gt;</span></tt>」と記述します。URIの拡張子の前に、現在のロケールから決定された（Javaのプロパティファイル形式の）接尾辞を付加する以外はPage式と同じです。接尾辞は現在のロケールと同一になるのではなく、URI＋ロケールに対応するリソースが存在するものに変換されることに注意して下さい。例えば/image/title_ja.jpgが存在して/image/title_ja_JP.jpgが存在しない場合、ロケールが「ja_JP」であっても最終的なURIは/image/title_ja.jpgになります。</li>
</ul>
</div>
</div>
<div class="section" id="talese381aepathe5bc8f">
<h3><a name="talese381aepathe5bc8f">TALESのPath式</a></h3>
<p>ここではFreyjaにおけるTALESのPath式の扱いに関して説明します。</p>
<div class="section" id="e69c80e5889de381aee382bbe382b0e383a1e383b3e38388e381aee8a7a3e6b1bae6898be9a086">
<h4><a name="e69c80e5889de381aee382bbe382b0e383a1e383b3e38388e381aee8a7a3e6b1bae6898be9a086">最初のセグメントの解決手順</a></h4>
<p>Path式の最初のセグメント（「first/second/third」の「first」の部分）は次の順序に従って解決されます。</p>
<ol>
<li>組み込み変数であれば変数の値。</li>
<li><tt class="docutils literal"><span class="pre">HttpServletRequest#getAttribute(&quot;first&quot;)</span></tt>の値がnullでなければその値。</li>
<li>セッションが張られていてかつ<tt class="docutils literal"><span class="pre">HttpSession#getAttribute(&quot;first&quot;)</span></tt>の値がnullでなければその値。</li>
<li><tt class="docutils literal"><span class="pre">ServletContext#getAttribute(&quot;first&quot;)</span></tt>の値がnullでなければその値。</li>
<li><tt class="docutils literal"><span class="pre">HttpServletRequest#getParameter(&quot;first&quot;)</span></tt>の値がnullでなければその値。</li>
<li><em>[Ymir拡張]</em> 処理対象のPageオブジェクトが存在してかつ<tt class="docutils literal"><span class="pre">Page#getFirst()</span></tt>メソッドまたは<tt class="docutils literal"><span class="pre">Page#isFirst()</span></tt>が存在し、メソッドの返り値がnullでなければその値。</li>
<li>上記のいずれにも該当しない場合はnull。</li>
</ol>
</div>
<div class="section" id="e382bbe382b0e383a1e383b3e38388e381aee8a7a3e98788">
<h4><a name="e382bbe382b0e383a1e383b3e38388e381aee8a7a3e98788">セグメントの解釈</a></h4>
<p>例えばPath式で「self/name」と書いた場合、selfを解決した結果であるオブジェクトについてセグメント「name」を解釈した結果が最終結果になります。</p>
<p>セグメントは基本的にはオブジェクトのプロパティと解釈されます。したがって、例えば上記の例ではselfに対応するオブジェクトについてgetName()メソッドを呼び出した結果が最終結果になります。</p>
<p>オブジェクトの型によっては以下のような特別な解釈がなされます。解釈は以下の表の上から順に適用され、結果がnullでExceptionがスローされなければさらに下の解釈が適用されます。</p>
<table border="1" class="docutils">
<colgroup>
<col width="48%" />
<col width="52%" />
</colgroup>
<thead valign="bottom">
<tr>
<th>オブジェクトの型</th>
<th>解釈</th>
</tr>
</thead>
<tbody valign="top">
<tr>
<td>org.seasar.ymir.Messages</td>
<td>
<p><em>[Ymir拡張]</em> セグメントが「%」で始まる場合、「%」を除いた文字列を引数としてgetMessage()を呼び出した結果。そうでない場合はセグメント文字列を引数としてロケールなしでgetProperty()を呼び出した結果。</p>
<p>結果がnullである場合はMessageNotFoundRuntimeExceptionがスローされる。</p>
</td>
</tr>
<tr>
<td>org.seasar.kvasir.util.collection.I18NPropertyReader</td>
<td><em>[Ymir拡張]</em> セグメントが「%」で始まる場合、「%」を除いた文字列を引数として現在のロケールについてgetProperty()を呼び出した結果。そうでない場合はセグメント文字列を引数としてロケールなしでgetProperty()を呼び出した結果。</td>
</tr>
<tr>
<td>org.seasar.kvasir.util.collection.PropertyReader</td>
<td><em>[Ymir拡張]</em> セグメント文字列を引数としてgetProperty()を呼び出した結果。</td>
</tr>
<tr>
<td>org.seasar.kvasir.util.collection.AttributeReader</td>
<td><em>[Ymir拡張]</em> セグメント文字列を引数としてgetAttribute()を呼び出した結果。</td>
</tr>
<tr>
<td>org.seasar.ymir.Notes</td>
<td><em>[Ymir拡張]</em> セグメントが「size」である場合、Notes#size()の結果。「size(XXX)」の形である場合、「XXX」の部分の文字列を引数としてNotes#size(String)を呼び出した結果。「categories」である場合、Notes#categories()の結果。それ以外の場合、セグメント文字列をNotesのカテゴリ文字列とみなして、そのカテゴリに属するNoteが存在するならNotes#get(カテゴリ文字列)の返り値。</td>
</tr>
<tr>
<td>org.seasar.ymir.Note</td>
<td><em>[Ymir拡張]</em> セグメントが「%value」である場合、Note#getValue()の返り値をキーとして現在のロケールについてメッセージリソースを検索した結果のメッセージ文字列。メッセージ文字列が見つからなかった場合はMessageNotFoundRuntimeExceptionがスローされる。</td>
</tr>
<tr>
<td>java.util.Collection</td>
<td>セグメントが「size」である場合、Collection#size()の結果。</td>
</tr>
<tr>
<td>配列型</td>
<td>セグメントが「length」である場合、配列の長さ。</td>
</tr>
<tr>
<td>java.lang.String</td>
<td>セグメントが「length」である場合、文字列の長さ。</td>
</tr>
<tr>
<td>java.util.Date</td>
<td>セグメント文字列中の「%」を「/」に置き換えたものをフォーマット文字列として日時を現在のロケールに従ってフォーマットした結果。例えばオブジェクトの表す日時が1983年1月14日でセグメント文字列が「yyyy%MM%dd」である場合、結果は「1983/01/14」となる。</td>
</tr>
<tr>
<td>全ての型</td>
<td>セグメント文字列をオブジェクトのプロパティ名とみなす。オブジェクトのプロパティの値が結果となる。該当するプロパティが存在しない場合はnull。</td>
</tr>
</tbody>
</table>
</div>
<div class="section" id="e789b9e588a5e381aarequeste382b9e382b3e383bce38397e382aae38396e382b8e382a7e382afe38388">
<h4><a name="e789b9e588a5e381aarequeste382b9e382b3e383bce38397e382aae38396e382b8e382a7e382afe38388">特別なrequestスコープオブジェクト</a></h4>
<p>Ymirでは以下のオブジェクトがrequestスコープにバインドされています。</p>
<table border="1" class="docutils">
<colgroup>
<col width="15%" />
<col width="85%" />
</colgroup>
<thead valign="bottom">
<tr>
<th>名前</th>
<th>値</th>
</tr>
</thead>
<tbody valign="top">
<tr>
<td>self</td>
<td>処理対象のPageオブジェクト。リクエストパスに対応するPageコンポーネントが存在しない場合は未定義</td>
</tr>
<tr>
<td>notes</td>
<td>制約違反のメッセージを保持するorg.seasar.ymir.Notesオブジェクト。制約違反でない場合は未定義</td>
</tr>
</tbody>
</table>
<p>したがって、例えばPageオブジェクトのtitleプロパティの値を参照したい場合は「self/title」と書けばよいことになります。</p>
</div>
</div>
</div>
</div>
</div>
        </div>
      
    </div>
    </div>
    <div class="footer-delimiter"></div>
    <div id="pane.footer" class="pane footer">
      <div id="org.seasar.kvasir.cms.pop.poweredByPop-1" class="pop org.seasar.kvasir.cms.pop.poweredByPop">
        <div class="body">Powered by Kvasir/Sora</div>
      </div>
    </div>
  </body>
</html>
