テンプレートAPI

ビュークラスはformatメソッドの引数に渡されたテンプレートに変更を加えてレスポンスとします。テンプレートはfeat.templateパッケージのテンプレートAPIを使って操作します。

テンプレートをロードする

ファイルからロード

// 2番目の引数をnullにするとエンコーディング名をHTMLから取得する
HTMLTemplate template = TemplateLoader.load(new File("shop_top_page.html"), null);

featのViewコンポーネントの場合

formatメソッドの引数で渡されるので、アプリケーションがロードする必要はありません。

public HTMLDocument format(HTMLDocument template, String[] params, ContextAccessor acc) throws Exception {
    ...
}

HTMLの要素を検索する

要素のIDで検索する

要素につけられたIDで要素を検索するには、ドキュメントノード(HTMLDocument)または要素ノード(HTMLElement)でfindElementメソッドを使います。

<html><body>
    <p id="hello">こんにちは</p>
</body></html>
try {
    HTMLElement hello = doc.findElement("hello");
    ...
}
catch(NodeNotFoundException ex) {
    // ノードが見つからなかったとき
    ...
}

class属性で検索する

ドキュメントノード、または要素ノードのfindElementByClassメソッドを使うとclass属性で要素の検索ができます。class属性に複数の名前が設定されている場合にも対応しています。

<td>
    <span class="price number">10,000</span>円
</td>
try {
    HTMLElement price = cell.findElementByClass("price");
    ...
}
catch(NodeNotFoundException ex) {
    // ノードが見つからなかったとき
    ...
}

XPathで検索する

ドキュメントノードのfindメソッドでXPathを使ったノードの検索ができます。

単一のノードの検索

try {
    HTMLElement title = (HTMLElement)doc.find("/html/head/title");
    ...
}
catch (NodeNotFoundException ex) {
    // ノードが見つからなかったとき
    ...
}

複数ノードの検索

// すべてのA要素を検索
HTMLNodeList link = doc.select("//a");

NodeSelectorで検索する

feat2.template.NodeSelectorクラスにはgetで始まる名前のメソッドとselectで始まる名前のメソッドがあります。get〜メソッドは単一のノードを、select〜メソッドは複数のノードを返します。

ノードが見つからなかったとき、get〜メソッドはnullを、select〜メソッドは空のリストやマップを返します。

// 顧客名を抽出
HTMLElement body; // body要素
...
HTMLNodeList customerNames = NodeSelector.selectElementsByClass(new NodeTreeIterator(body), "customer-name");

NodeSelectorと組み合わせて使うと便利なイテレータ

NodeSelectorのメソッドのほとんどはIteratorを引数にとります。HTMLのツリーからノードを見つけ出すにはツリーのノードを順にたどる必要がありますが、NodeTreeIteratorを使うと指定のノードを頂点とするノードツリーをたどることができます。これにより、HTMLツリーの任意の部分ツリーからノードを検索することができます。

// ドキュメントで最初に見つかったtitle要素を返す
HTMLELement title = NodeSelector.getTag(new NodeTreeIterator(doc), "title");

NodeListIteratorは指定のノードの兄弟ノードをたどります。

// 表のtr要素を取り出す
try {
    HTMLElement table = doc.findElement("search-results");
    HTMLNodeList rows = NodeSelector.selectTags(new NodeListIterator(table.getFirstChild()), "tr");
    ...
}
catch(NodeNotFoundException ex) {
    ...
}

要素の作成

新しい要素を作成するときはfeat2.template.NodeFactoryクラスを使います。NodeFactoryクラスでは要素のほか、ドキュメントノード、テキストノード、注釈ノードも作ることができます。

HTMLElement copyright = NodeFactory.createElement("b", true);
copyright.addText("Copyright (C) 2006 ...");
body.addChild(copyright);

ノードの複製

ノードをコピーするにはノードのcopyメソッドを使います。引数deepがtrueの場合、ノードツリー全体をコピーします。引数deepがfalseの場合でもオブジェクトのプロパティはディープコピーとなります。copyメソッドが何をコピーするかは下の表を参照してください。

引数deepの値 子ノード 属性 親ノードへの参照 前の兄弟ノードへの参照 次の兄弟ノードへの参照
true ディープコピー ディープコピー コピーしない コピーしない コピーしない
false コピーしない ディープコピー コピーしない コピーしない コピーしない

コピーするノードに要素ノードが含まれている場合は注意が必要です。copyメソッドは要素のID属性もコピーするので、コピーした要素をドキュメントツリーに追加したときにIDが重複してしまう可能性があります。このような場合、ID属性を削除するコードをその都度書かなければなりません。

テキストノードを操作する

テンプレートAPIではテキストノードをノードオブジェクトとして意識する必要はあまりないかもしれません。CompositeNodeのメソッドでテキストノードを操作する場合がほとんどです。また、CompositeNodeやHTMLTextのメソッドでテキストを読み書きするとき、HTMLの特殊文字は自動的にエスケープ/アンエスケープされます。

エスケープしないで文字列を追加したい場合は、HTMLTextのsetRowTextメソッドを使います。

要素を削除する

ノードをドキュメントツリーから削除するときはHTMLNodeのdetachメソッドを使います。このメソッドはノードを削除するわけではなく、指定ノードの親ノードと兄弟ノードとの関係を断ち切るだけです。参照がなくなればオブジェクトはいつか削除されます。

detachメソッドで切り離したサブツリーは再びドキュメントツリーに追加できます。元のドキュメントツリーだけでなく、どのドキュメントツリーにも追加できます。ただし、同じインスタンスを複数のドキュメントツリーに追加することはできません。

フォームに値を入れる

フォームもドキュメントツリー以下の要素の集合でしかないので、ほかの要素と同様に扱うことが可能です。しかし、ドキュメントツリーを直接操作してフォームの値を読み書きするのは非常に面倒です。テンプレートAPIにはフォームの値の読み書きを簡単にするためにfeat2.template.form.Formクラスがあります。

Formオブジェクトの作成

Form form = new Form(formElement);

コントロールに値を設定する

単一の値をセットする場合。

form.setValue("controlName", "value");

リストやチェックボックスなど、複数の値を許容するコントロールに値をセットする場合。

form.setValues("controlName", new String[] {"tokyo", "kanagawa"});

コントロールのラベルを設定する

コントロールに対応したlabel要素の値を設定することができます。input要素のボタンの場合はlabel要素ではなくinput要素のvalue属性が設定されます。

form.setLabel("controlName", "送信");

名前を共有するラジオボタン、チェックボックスの場合は同名のコントロールに対応したlabel要素を一度に指定します。Formクラスでは、名前を共有するコントロールのラベルを個別に設定することはできません。

form.setLabel("controlName", new String[] {"東証", "大証", "名証", "JQ", "HC"});
$Id: template.html 220 2007-07-16 10:32:15Z sugimotokenichi $