SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

特集記事

テンプレートエンジンNVelocityを活用してテキストを生成する

NVelocityを利用して保守性の高いアプリケーションを構築する


  • X ポスト
  • このエントリーをはてなブックマークに追加

プログラムの記述

 引き続き、プログラムを記述していきます。プログラムでは、VelocityクラスとVelocityContextクラスを利用します。また、NVelocity固有の例外をハンドリングするため、例外クラスも利用します。

クラス名 名前空間 説明
Velocity NVelocity.App NVelocity本体。テンプレートとコンテキストのマージを実行するクラス
VelocityContext NVelocity テンプレートから参照できるコンテキスト
ResourceNotFoundException NVelocity.Exception テンプレートファイルが見つからない場合に発生する例外
ParseErrorException NVelocity.Exception テンプレートの内容が不正な場合に発生する例外

 そのため、フォームの一番上で次のようなusing設定を行っておきます。

MainForm.cs
using NVelocity;
using NVelocity.App;
using NVelocity.Exception;

プログラムの全体像

 btnMergeボタンがクリックされた場合、次のようにNVelocityを利用します。詳細については、この後で個別に説明していきますので、ここでは全体の雰囲気をつかんでもらえれば結構です。

MainForm.cs
//NVelocityの初期化
Velocity.Init();

//コンテキストの設定
VelocityContext ctx = new VelocityContext();

//名前をセット
ctx.Put("name", this.txtName.Text);

//住所をセット
ctx.Put("address", this.txtAddress.Text);

//備考をセット
ctx.Put("remarks", this.txtRemarks.Text);

//注文をセット
ArrayList list = new ArrayList();
foreach(string item in this.lstOrder.SelectedItems)
{
    list.Add(item);
}
ctx.Put("orderlist",list);

//配送希望日をセット
ctx.Put("senddate", this.dtpSendDate);

try
{
    //結果を格納するStringWriter
    System.IO.StringWriter resultWriter =
        new System.IO.StringWriter();
    //Shift-JISのテンプレートファイルを読み込み、コンテキストとマージ
    Velocity.MergeTemplate("../../mail.vm",
        "Shift-JIS",ctx, resultWriter);
    //結果を画面に表示
    this.txtResult.Text = resultWriter.GetStringBuilder().ToString();

}
catch(ResourceNotFoundException ex)
{
    MessageBox.Show("テンプレートファイルが見つかりませんでした",
        "エラー",MessageBoxButtons.OK,MessageBoxIcon.Warning);
}
catch(ParseErrorException ex)
{
    MessageBox.Show("テンプレートの解析時にエラーが発生しました",
        "エラー",MessageBoxButtons.OK,MessageBoxIcon.Warning);
}

プログラムの詳細解説

NVelocityの初期化

 最初に、InitメソッドによってNVelocityの初期化を行います。NVelocityを利用するためにはこのInitメソッドの呼び出しが必須となります。

「MainForm.cs」 NVelocityの初期化
Velocity.Init();

 引数なしでInitメソッドを実行した場合には、実行ファイルと同じフォルダにある「NVelocity.properties」ファイルが読み出されます。ただし「NVelocity.properties」ファイルが存在しなくてもエラーにはならず、デフォルト値によってNVelocityは初期化されます。

 初期設定ファイルには、次のようにデフォルトエンコーディングなどを指定できます。

「NVelocity.properties」の設定例
#ファイル読み込み時のデフォルトエンコード
input.encoding=Shift-JIS
#ファイル書き出し時のデフォルトエンコード
output.encoding=Shift-JIS
# foreach内で使用可能なカウンタ変数名
directive.foreach.counter.name = velocityCount
# foreach内で使用可能なカウンタ変数名の初期値
directive.foreach.counter.initial.value = 1

 なお、Initメソッドの引数にプロパティファイル名を指定することもできます。

コンテキスト設定

 コンテキストはテンプレートファイルから参照できる領域にあたります。テンプレートから利用する変数をPutメソッドによって追加していきます。

「MainForm.cs」 コンテキスト設定
//コンテキストの設定
VelocityContext ctx = new VelocityContext();

//名前をセット
ctx.Put("name", this.txtName.Text);

//住所をセット
ctx.Put("address", this.txtAddress.Text);

//備考をセット
ctx.Put("remarks", this.txtRemarks.Text);

//注文をセット
ArrayList list = new ArrayList();
foreach(string item in this.lstOrder.SelectedItems)
{
    list.Add(item);
}
ctx.Put("orderlist",list);

//配送希望日をセット
ctx.Put("senddate", this.dtpSendDate);

 ここでは、VelocityContextクラスをインスタンス化し、Putメソッドによってキーと値を設定しています。基本的にコンテキストには文字列を格納しますが、オブジェクトを格納することも可能です。ここでは文字列、ArrayList、DateTimePickerコントロールをコンテキストに設定しています。

テンプレートとコンテキストのマージ

 最後にテンプレートとコンテキストのマージ(合併)を行います。マージを行った結果はWriterに格納されるため、StringWriterを生成した後で、VelocityクラスのMergeTemplateメソッドを呼び出します。

「MainForm.cs」 テンプレートとコンテキストのマージ
//結果を格納するStringWriter
System.IO.StringWriter resultWriter = new System.IO.StringWriter();
//Shift-JISのテンプレートファイルを読み込み、コンテキストとマージ
Velocity.MergeTemplate("../../mail.vm",
    "Shift-JIS",ctx, resultWriter);
//結果を画面に表示
this.txtResult.Text = resultWriter.GetStringBuilder().ToString();

 MergeTemplateメソッドでは次の4つの引数を指定します。

  1. テンプレートファイル名
  2. テンプレートファイルの文字コード(省略時/初期設定ファイル未設定時は西欧諸語の「ISO-8859-1」が適用)
  3. コンテキスト
  4. 結果を格納するWriter

 MergeTemplateメソッドの実行後に、Writerからマージされたアウトプットを取り出すことができます。ここでは、StringWriterを使っていますが、StreamWriterなどを利用すればファイルに保存することもできるでしょう。

Exceptionについて

 NVelocityでは、テンプレートファイルのマージ処理において例外が発生する可能性があるため(テンプレートを事前にコンパイルしてソースをチェックすることができないため)、確実にエラーハンドリングを行う必要があります。

「MainForm.cs」 エラーハンドリング
try{
    Velocity.MergeTemplate("../../mail.vm",
        "Shift-JIS",ctx, resultWriter);
}
catch(ResourceNotFoundException ex)
{
    MessageBox.Show("テンプレートファイルが見つかりませんでした",
        "エラー",MessageBoxButtons.OK,MessageBoxIcon.Warning);
    Console.WriteLine(
        "■テンプレートファイルが見つかりませんでした\n\n"
        + ex.ToString());
}
catch(ParseErrorException ex)
{
    MessageBox.Show("テンプレートの解析時にエラーが発生しました",
        "エラー",MessageBoxButtons.OK,MessageBoxIcon.Warning);
    Console.WriteLine(
        "■テンプレートの解析時にエラーが発生しました\n\n"
        + ex.ToString());
}

 テンプレートファイルが見つからないときに発生する「ResourceNotFoundException」と、テンプレートファイルの構文エラーで発生する「ParseErrorException」をハンドリングするように心掛けましょう。なお、コンテキストに設定されていない変数をテンプレートから参照した場合、エラーは発生せず変数名がそのまま表示されるだけなので注意してください。

 以上でアプリケーションは完成です。プログラムを動かして、想定どおりメールの本文が生成されているか確認してみてください。

まとめ

 最後に、NVelocityについてまとめます。

  • NVelocityはテンプレートという雛形からテキストを生成できるテンプレートエンジンである。
  • テンプレートはVTL(Velocity Template Language)という言語で記述する。
  • NVelocityクラスとNVelocityContextクラスを使ってプログラミングを行う。
  • テンプレートとプログラムで共有する値はコンテキスト(NVelocityContextクラス)に設定する。
  • NVelocityクラスのMergeTemplateメソッドを呼び出すと、テンプレートとコンテキストがマージされ、結果を出力することができる。

 NVelocityの最新バージョンはまだ0.5ですが、既にMonoRailNHibernateContribといったオープンソースプロダクトで利用されています。また、今後のシステム開発の選択肢の一つとして、テンプレートエンジンという考え方を理解しておくと良いのではないでしょうか。

参考資料

  1. NVelocity(SourceForge:英語)
  2. Castle Project(最新ソース:英語)
  3. Template merging with NVelocity and ASP.NET(NVelocityラッパークラスの紹介:英語)
  4. CSharp-Source.NET(C#のオープンソーステンプレートエンジン一覧:英語)
  5. SharpToolbox Code generation(コード生成プロダクト一覧:英語)
  6. JaJakarta Velocity-1.3.1 日本語ドキュメント注2
  7. Jakarta Velocityでテンプレートを変換しメールを送信する注2
注2
 NVelocityではありません。
 

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
特集記事連載記事一覧

もっと読む

この記事の著者

WINGSプロジェクト 青木 淳夫(アオキ アツオ)

WINGSプロジェクトについて>有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書記事多数。 RSS X: @WingsPro_info(公式)、@WingsPro_info/wings(メンバーリスト) Facebook

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるReact実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/373 2008/08/19 20:27

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング