XML 構文 JSP

XML 構文 JSP

JSP 1.2 から JSP ファイル全体を XML で記述できるようになりました。 これにより要素の整合性が取れていないような記述は事前に全てエラーとして検知することが出来ます。 またスクリプトレットなどのような JSP 構文の振り替え記述が可能になったため JSP ソースの可視性を向上させることが出来ます。

<?xml version="1.0"?>
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="1.2">
<jsp:directive.page contentType="text/html;charset=UTF-8" session="false" />
<html>
...
</html>
</root>

XML 構文の JSP の拡張子は .jspx です。 また XML 構文で記述された JSP のデフォルトの Content-Type は text/xml;charset=UTF-8 です (これは <jsp:directive.page> で変更可能です)。

原則的に JSP 構文で出来て XML 構文で出来ないこと、またその逆はありません。 ただ XML 構文は厳格さを要求するあまり記述が冗長になりがちです。 一度 JSP プロセッサによりコンパイルされれば通常の JSP と変わりありませんので、 ブラウザに表示させる JSP をどちらで記述するかは好みやプロジェクトの方針と 言えます。ただページを XHTML に対応させたい場合や、通信先が Ajax のように そもそも XML で返したいような場合には、構文のルーズさがない XML 構文を 使用するほうが有利と言えます。

XML 構文の JSP を使用するに際して従来の開発者が注意すべき点は以下の通りです (XSL についての知識があれば若干理解は早いと思われます)。

  • <br>, <img> など、 終了要素を省略して記述できた要素は <br/> と記述する。
  • 内容のないタグは <foo/> のように自動的に畳み込まれる。
  • 暗黙的に使用できていた <jsp:...> という名前空間は <jsp:root> 要素で明示的に宣言する。
  • スクリプトレットなどの JSP 構文やディレクティブは後述の <jsp:...> で記述する。
  • タグライブラリの名前空間に XML に準拠した xmlns を使用する。

空要素の自動畳み込みにより <script src="..."></script><script src="..."/> と出力され、これは Internet Explorer では script タグが終了していないものと解釈されてしまいます。このような場合、 <script src="...">;</script> のように タグの内部に実行に影響のない文字を記述することで回避することが出来ます。

JSP構文/ディレクティブの置き換え

XML 構文に対応するため、<%= %>, <%@page%> などの JSP 構文やディレクティブに対応する XML 要素が追加されています (これらは通常の JSP からも使用することが出来ます)。 <%@taglib%&> 以外のディレクティブに関してはディレクティブ名を <jsp:directive.name ... /> に置き換えて同じ属性が 指定できるようになっています。

JSP構文 XML構文
&lt; &amp;lt; HTML 文字実体参照
&#xFFFF; &amp;#xFFFF; HTML 数値文字参照
<%-- comment --%> <!-- comment --> コメント
<%! decl %> <jsp:declaration>decl</jsp:declaration> 宣言
<%= expr %> <jsp:expression>expr</jsp:expression> 評価
<% script %> <jsp:scriptlet>script</jsp:scriptlet> スクリプトレット
<@ attribute ... %> <jsp:directive.attribute ... /> タグファイル属性
<@ include ... %> <jsp:directive.include ... /> インクルード
<@ page ... %> <jsp:directive.page ... /> JSP 宣言
<@ tag ... %> <jsp:directive.tag ... /> タグファイル宣言
<@ taglib ... %> <tag-name
xmlns:prefix="{uri | urn:jsptld:path | urn:jsptagdir:/WEB-INF/tags[/subdir]+}" >
タグライブラリ宣言
<@ variable ... %> <jsp:directive.variable ... /> タグファイル変数宣言

XML 構文の JSP では宣言やスクリプトレットなどの Java コードを記述する部分でも XML として評価の対象となります。 < などの文字は &lt; などのように XML エスケープするするか、 あるいは <jsp:scriptlet><![CDATA[ script ]]></jsp:scriptlet> のようにコード部分全体を CDATA セクションで囲う必要があります。

要素の動的構築

従来の JSP で許されていた要素内でのスクリプトレットやタグ記述は:

<span style="color:<foo:color />;"><foo:message /></span>

XML 構文では許可されません。この振り替え策として以下の要素が用意されています。

要素名
<jsp:element> 要素定義
<jsp:attribute> 属性定義
<jsp:body> 要素内定義

例えば前述の例は以下のように記述することが出来ます (XSL の <xsl:element> と似ています)。

<jsp:element name="span">
  <jsp:attribute name="style">color:<foo:color />;</jsp:attribute>
  <jsp:body><foo:message /></jsp:body>
</jsp:element>

なお、EL は要素の属性値に埋め込みで記述することが出来ます。

名前空間と拡張タグライブラリ

従来の JSP 構文では <%@taglib%> ディレクティブを使用して拡張タグの 名前空間を定義してきましたが、XML 構文ではこれに変わって XML 名前空間を使用します。

<fmt:formatDate
  xmlns:fmt="http://java.sun.com/jsp/jstl/fmt"
  type="both" value="${cur}" />
Nov 22, 2008 3:51:50 PM

上記は個別の要素で定義する方法です。名前空間に関連付けられた拡張タグをページ内のどこから でも利用できるようにするにはトップレベルの <jsp:root> で定義します。

<?xml version="1.0"?>
<jsp:root
  xmlns:jsp="http://java.sun.com/JSP/Page"
  xmlns:c="http://java.sun.com/jsp/jstl/core"
  version="2.0">
...
<c:out value="${cur}" />
Sat Nov 22 15:51:50 JST 2008

なお、JSP プロセッサが xmlns で宣言されていない名前空間を検出した場合は コンパイルエラーが発生します。

<%@taglib%> ディレクティブでは以下の 3 通りの方法で拡張タグ を定義することが出来ました。

  1. web.xml で定義、あるいはサーブレットコンテナがデフォルトで提供する URL を uri 属性に指定する。
  2. TLD ファイルのパスを直接 uri に記述する。
  3. タグファイルのディレクトリを直接 tagdir に記述する。

これらそれぞれに対応する xmlns の記述は以下のようになります。

<%@taglib prefix="foo"
  uri="http://..." xmlns:foo="http://..."
  uri="/path/foo.tld" xmlns:foo="urn:jsptld:/path/foo.tld"
  tagdir="/WEB-INF/tags/foo" xmlns:foo="urn:jsptagdir:/WEB-INF/tags/foo"
%>

実行例

以下はサンプルとして作成した xmljsp-sample.jspx の生ソース 及び実行結果をこの JSP から読み出して表示しています (結果をこのページに埋め込めるように <html><body> は省略してあります)。

<?xml version="1.0" encoding="UTF-8"?>
<jsp:root
    xmlns:jsp="http://java.sun.com/JSP/Page"
    xmlns:c="http://java.sun.com/jsp/jstl/core"
    version="1.2">
    <jsp:directive.page session="false" />
    <jsp:directive.page contentType="text/html; charset=UTF-8" />
<jsp:scriptlet>
  response.setHeader("Cache-Control", "no-cache");
</jsp:scriptlet>

<table border="1">
<tr>
    <td>コメント</td>
    <td><!-- これはコメントです --></td>
</tr>
<tr>
    <td>テキスト</td>
    <td>通常のテキスト</td>
</tr>
<tr>
    <td>テキスト</td>
    <td><jsp:text>通常のテキスト</jsp:text></td>
</tr>
<tr>
    <td>評価</td>
    <td>1 + 1 := <jsp:expression>1 + 1</jsp:expression></td>
</tr>
<tr>
    <td>スクリプトレット</td>
    <td>偶数 := <jsp:scriptlet><![CDATA[
        for(int i=0; i<10; i+=2){
            out.print(i+",");
        }
    ]]></jsp:scriptlet></td>
</tr>
<tr>
    <td>宣言</td>
    <td>
    <jsp:declaration>
        long load = System.currentTimeMillis();
    </jsp:declaration>
    PAGE UPTIME: <jsp:expression>
        java.text.NumberFormat.getNumberInstance().format(
            System.currentTimeMillis() - load)
    </jsp:expression>ミリ秒
    </td>
</tr>
<tr>
    <td>要素の動的構築</td>
    <td>
        <jsp:element name="span">
            <jsp:attribute name="style">color:<jsp:scriptlet><![CDATA[
                java.util.Random random = new java.util.Random();
                String[] color = {"red","green","blue","cyan","magenta","yellow"};
                out.write(color[random.nextInt(color.length)]);
            ]]></jsp:scriptlet>;</jsp:attribute>
            <jsp:body>色が変わります</jsp:body>
        </jsp:element>
    </td>
</tr>
<tr>
    <td>拡張タグ (xmlns全体指定)</td>
    <td>
        <jsp:useBean id="cur" class="java.util.Date" />
        <c:out value="${cur}" />
    </td>
</tr>
<tr>
    <td>拡張タグ (xmlns個別指定)</td>
    <td>
    	<fmt:formatDate
            xmlns:fmt="http://java.sun.com/jsp/jstl/fmt"
            type="both" value="${cur}" />    	
    </td>
</tr>
</table>

</jsp:root>

以下、実行結果です。更新ボタンを押すと内容が更新されます。

コメント
テキスト通常のテキスト
テキスト通常のテキスト
評価1 + 1 := 2
スクリプトレット偶数 := 0,2,4,6,8,
宣言 PAGE UPTIME: 276,828,815ミリ秒
要素の動的構築色が変わります
拡張タグ (xmlns全体指定)Sat Nov 22 15:51:50 JST 2008
拡張タグ (xmlns個別指定)Nov 22, 2008 3:51:50 PM