Agusa Lab. > Webware Project > GrapeWeb
 

Cocoon2 チュートリアル (後編)

概要

前編では Cocoon の概要および Cocoon プログラミングについて説明しました。後半では Cocoon によるプログラミングの応用例として Sapid の SPIE (Source Program Information Explorer) の Cocoon 版である SPIECE (Source Program Information Explorer - Cocoon Edition) について説明します。

SPIE

SPIE は、クロスリファレンス情報をWebページとして表示するソフトウェアです。まず SPIE の構成について簡単に説明 します。

SPIEの例はこちらで参照できます。

spie

SPIEでは上図のような画面分割のためにフレームを用いています。各フレームの中は XML + XSLT で表示されています。 XML と XSLT はクライアントサイドに送られているため、XSLT の適用はクライアントサイドで行われます。

spieの表示方式

SPIECEの構成

ここではSPIECEの構成についての外観について説明します。

SPIE のようにフレームで表示するのではなく、サーバサイドで一枚のHTMLとして生成し、クライアントに返すようにします。

フレームの代わりにテンプレートを作成し、部品を作成し埋め込んでいきます。テンプレートをXSPで作成し、埋め込み作業をXSLT で行います。各部品は別のpipelineでXMLとして生成します。このため、SPIECEのpipelineは2段になっています。

以下のような pipeline で実現します。

spiece-pipeline

以降はSPIECEのソースコードを見て行きます。

SPIECEの詳細

まずsitemap.xmapにおけるpipelineの断片を示します。

    <map:match pattern="**/index.html">
      <map:generate type="serverpages" src="index.xsp"/>
      <map:transform src="xslt/spie.xsl">
        <map:parameter name="use-request-parameters" value="true"/>
      </map:transform>
      <map:serialize type="html"/>
    </map:match> 
    <map:match pattern="**/spie-index.xml">
      <map:generate src="{1}/spie-index.xml"/>
      <map:transform src="xslt/spie-index.xsl">
        <map:parameter name="use-request-parameters" value="true"/>
      </map:transform>
      <map:serialize type="xml"/>
    </map:match>
    <map:match pattern="**/spec-*.xml">
      <map:generate src="{1}/spec-{2}.xml"/>
      <map:transform src="xslt/spec.xsl">
        <map:parameter name="use-request-parameters" value="true"/>
      <map:serialize type="xml"/>
    </map:match>
    <map:match pattern="**/list-*.xml">
      <map:generate src="{1}/list-{2}.xml"/>
      <map:transform src="xslt/list.xsl">
        <map:parameter name="use-request-parameters" value="true"/>
      </map:transform>
      <map:serialize type="xml"/>
    </map:match>
	    

上図で説明したように4つのpipeline定義で構成されています。

まず"**/index.html"は各ディレクトリのindex.htmlが要求された場合の定義です。"**"はディレクトリを またがってマッチする0文字以上の文字列を表します。

index.xspはテンプレート代わりに利用し、spie.xslで他のpipelineに対してXMLを要求して埋め込みます。

テンプレート代わりに使っているindex.xspを見てみましょう。

<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR
/xhtml1/DTD/xhtml1-frameset.dtd">
<xsp:page language="java"
          xmlns:xsp="http://apache.org/xsp"
          xmlns:xsp-request="http://apache.org/xsp/request/2.0">

<body>
<xsp:logic>
  String url = <xsp-request:get-requested-url/>;
  url = url.substring(0, url.lastIndexOf("/"));
</xsp:logic>
<url><xsp:expr>url</xsp:expr></url>

<div style="position:fixed; height: 400px">
<include name="category"/>
<div style="overflow: auto; height: 100%; max-width:14em" >
<include name="list"/>
</div>
</div>
<div style="margin-left: 14em">
<include name="spec"/>
</div>
</body>
</xsp:page>
    	

include要素が埋め込む場所です。XSLTでinclude要素の位置にXMLを埋め込んでいきます。

埋め込み役のspie.xslを見てみましょう。

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:xsp-request="http://apache.org/xsp/request/2.0"
                xmlns:xsp="http://apache.org/xsp"
                xmlns:html="http://www.w3.org/1999/xhtml"
                version="1.0">
  <xsl:output method="xml" encoding="UTF-8" indent="no"
    doctype-public="-//W3C//DTD XHTML 1.0 Traditional//EN"
    doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"/>

  <xsl:param name="category"/>
  <xsl:param name="list"/>
  <xsl:param name="spec"/>

  <xsl:template match="/">
    <html>
      <head>
        <meta name="robots" content="noindex,nofollow" />
        <title>SPIE: Program: test </title>
        <link rel="stylesheet" href="SPIE.css" type="text/css" />
        <!--link rel="stylesheet" href="new.css" type="text/css" /-->
      </head>
      <xsl:apply-templates/>
    </html>
  </xsl:template>

  <xsl:template match="url">
  </xsl:template>

  <xsl:template match="include">
    <xsl:variable name="context" select="//url/text()"/>
    <xsl:variable name="category_path"
                  select="concat($context, 
                          '/',
                          $category, 
                          '?category=',
                          $category,
                          '&list=',
                          $list,
                          '&spec=',
                          $spec)"/>
    <xsl:variable name="list_path" 
                  select="concat($context, 
                          '/', 
                          $list,
                          '?category=',
                          $category,
                          '&list=',
                          $list,
                          '&spec=',
                          $spec)"/>
    <xsl:variable name="spec_path"
                  select="concat(
                          $context, 
                          '/', 
                          $spec,
                          '?category=',
                          $category,
                          '&list=',
                          $list,
                          '&spec=',
                          $spec)"/>
    <xsl:choose>
      <xsl:when test="@name='category'">
        <xsl:copy-of select="document($category_path)/html:html/html:body/*"/>
        <br/><br/>
      </xsl:when>
      <xsl:when test="@name='spec'">
        <xsl:copy-of select="document($spec_path)/html:html/html:body/*"/>
      </xsl:when>
      <xsl:when test="@name='list'">
        <xsl:copy-of select="document($list_path)/html:html/html:body/*"/>
      </xsl:when>
    </xsl:choose>
  </xsl:template>
  
  <xsl:template match="node()|@*">
    <xsl:copy>
      <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>
		

変換するのはinclude要素だけなので最後の規則では、include要素以外はそのままコピーします。

include要素に対する変換ではinclude要素のname属性に対応してXMLの生成要求をもう一度投げそれを埋め込みます。

このときパラメータで生成するXMLを指定しています。

まとめ

前編・後編を通してCocoonの概要から応用までを説明しました。XMLを使ってWebアプリケーションを作成する場合、 Cocoonは非常に有力なフレームワークです。ぜひ一度Cocoonを自分でさわってみて、その強力さを実感してみてください。

by Ryo SUETSUGU