HTMLテンプレートの再帰でツリー型のデータを表示する

ツリー構造を持ったデータを、Mayaaのテンプレートを再帰的にinsertすることで表示する

ソース

こういう階層構造のデータがあったとする

package sample.model;

import java.util.Arrays;
import java.util.List;

public class SampleUtils {
    /** 階層構造を持ったデータクラス */
    public static class Node {
        public String name;	// 名前
        public List children;	// 子要素のリスト
    }
    /** Nodeのツリー構造を初期化して戻す */
    public static Node getRootNode() {
        return
            new Node() {{name="アマゾネス";children = Arrays.asList(
               new Node() {{name="ヴァルキリー";children = Arrays.asList(
                   new Node() {{name="フレイア";}}
               );}},
               new Node() {{name="クレリック";children = Arrays.asList(
                   new Node() {{name="プリースト";children = Arrays.asList(
                       new Node() {{name="ビショップ";}}
                   );}}
               );}},
               new Node() {{name="ウィッチ";}},
               new Node() {{name="プリンセス";}}
           );
        }};
    }
}

このデータを表示するエントリーページ
index.html:

<html xmlns:m="http://mayaa.seasar.org">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS">
<body>
    <h1>tree例</h1>
    <!-- この下にツリーの中身を表示 -->
    <div m:id="tree"></div>
</body>
</html>

index.mayaa:

<?xml version="1.0" encoding="Shift_JIS"?>
<m:mayaa xmlns:m="http://mayaa.seasar.org">
    <m:beforeRender>
    	var rootNode = Packages.sample.model.SampleUtils.rootNode;
    </m:beforeRender>
    <m:insert m:id="tree" m:path="./tree.html" node="${rootNode}"/>
</m:mayaa>

便宜的にm:beforeRenderで表示用データを取得している。
ツリーのルート要素を、"node"というパラメータ名でtree.htmlに渡している。


tree.htmlでは、nodeの情報(name)を表示しつつ、子要素のリスト(children)を一つずつtree.htmlを使って表示している。
tree.html:

<html xmlns:m="http://mayaa.seasar.org">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS">
<body>
↓body内部だけが表示されるよ
<div m:id="body">

<span m:id="name">名前</span>
<div m:id="showsChildren"><!-- childrenがある場合中身を表示 -->
    <ul>
    <div m:id="children">
        <li><div m:id="childTree">次の階層</div></li>
    </div>
    </ul>
</div>

</div>
</body>
</html>

tree.mayaa:

<?xml version="1.0" encoding="Shift_JIS"?>
<m:mayaa xmlns:m="http://mayaa.seasar.org">

    <m:doRender m:id="body" />

    <m:write m:id="name" value="${binding.node.name}"/>
    <m:if m:id="showsChildren" test="${binding.node.children != null}"/>
    <m:forEach m:id="children" items="${binding.node.children}" var="child"/>
    <m:insert m:id="childTree" m:path="./tree.html" node="${child}"/>
</m:mayaa>

一つ上の階層から渡されたパラメータ(node=)で渡されたノード情報は、${binding.node}で参照出来る。
上の例では、${binding.node.children}の各要素(child)について、再度tree.html自身をinsertすることで再帰的に内容を表示している。


こんな感じの出力が得られる:

tree例

アマゾネス

  • ヴァルキリー
    • フレイア
  • クレリック
    • プリースト
      • ビショップ
  • ウィッチ
  • プリンセス

動作環境

  • J2SE 5.0
  • Tomcat 6(たぶん5.5でも大丈夫)
  • Mayaa 1.1.9に付いてくるjar

まとめ

スコープ管理がまともなテンプレートエンジンでないと、この方法は使えない。(Mayaaの他にFaceletsやPerlのMasonはOKだった。)


実用的な所では、ツリー構造の掲示板の内容を出したりするのに使えると思う。