テキストテンプレートエンジン NVelocity の使い方

# このドキュメントの内容 #

.NET Framework 用のテキストテンプレートエンジン `NVelocity` の簡単な使い方を説明します。

## NVelocity ##

Java のテキストテンプレートエンジン`Velocity`の .NET 移植版です。
SOURCEFORGE にあるものは 0.4.1 を最後に開発が停止しており、現在は Castle Project に移管されているようです。残念ながら活発に開発が継続されているようではありませんが…。

[【SOURCEFORGE】](http://nvelocity.sourceforge.net/)
[【Castle Project】projects](http://www.castleproject.org/projects/)
[【NuGet】NVelocity](https://www.nuget.org/packages/NVelocity/)

ここには NVelocity に関する情報はほとんどありません。Other Projects の欄に GitHub へのリンクがありますが、リファレンスなどを見つけることはできませんでした。機能的にはほぼ`Velocity`と同じですので、`Velocity`のリファレンスを参照するとよいです。

実行時にテンプレートファイルを外部から読み込んでテキストを生成するアプリケーションを簡単に作ることができます。.NET Framework 用のテキストテンプレートエンジンといえば`T4`が最も有名ですが、事実上 VisualStudio 専用と言える`T4`との使い分けができると思います。


## テキストの生成方法 ##

1. コンテキストに変数と値を格納します。
2. テンプレートファイルパスとコンテキストを指定してテキストを生成します。

```C#

// 初期処理
NVelocity.App.Velocity.Init();

// コンテキストを生成する
NVelocity.VelocityContext context = new NVelocity.VelocityContext();

// 変数と値の組み合わせを格納する
context.Put("name", "あいうえお");

// テンプレートファイルを指定してテキストを生成する
StringBuilder sb = new StringBuilder();
using (StringWriter writer = new StringWriter(sb))
{
    NVelocity.App.Velocity.MergeTemplate("test.vm", "shift-jis", context, writer);
}
Debug.WriteLine(sb.ToString());

```

## テンプレートの構文 ##

### 変数による値の置き換え ###

変数名の前に $ をつけます。

```text:テンプレート
名前:$name
```
```C#:コンテキスト
context.Put("name", "あいうえお")
```
```text:生成結果
名前:あいうえお
```

大文字小文字は区別されます。変換は行われず、そのまま出力されます。

```text:テンプレート
名前:$Name
```
```C#:コンテキスト
context.Put("name", "あいうえお")
```
```text:生成結果
名前:$Name   // 変換されない
```

変数名に使用できる文字は a～z A～Z 0-9 _ - です。
このうち先頭の文字として使用できるのは a～z A～Z _ です。

```text:テンプレート
名前:$_name1
名前:$-name1
名前:$1name
```
```C#:コンテキスト
context.Put("_name1", "あいうえお")
context.Put("-name1", "あいうえお")
context.Put("1name", "あいうえお")
```
```text:生成結果
名前:あいうえお
名前:$-name   // 変換されない
名前:$1name   // 変換されない
```

変数名は {} で囲むことを推奨します。どこまでが変数名であるかがわかりやすくなります。なお、変数名のすぐ後ろに a～z A～Z 0-9 _ - が続く場合は {} で囲まないと正しく変数名が認識されません。

```text:テンプレート
名前:<$name>
名前:-$name-
名前:-${name}-
```
```C#:コンテキスト
context.Put("name", "あいうえお")
```
```text:生成結果
名前:<あいうえお>
名前:-$name-   // 変換されない
名前:-あいうえお-
```

$ と変数名の間に ! を付加すると、コンテキストで値が指定されなかった、または null が指定されたときに "" に変換されます。

```text:テンプレート
名前:<$unknown_name>
名前:<$!unknown_name>
名前:<$!{unknown_name}>
```
```C#:コンテキスト
context.Put("name", "あいうえお")
```
```text:生成結果
名前:<$unknown_name>
名前:<>
名前:<>
```

### 変数のメンバの呼び出し ###

変数に指定した値の型に定義されているプロパティやメソッドを呼び出すことができます。メンバ名の大文字小文字は区別されないようです。

```text:テンプレート
名前の長さ：${name.Length}
名前の長さ：${name.length}
名前の先頭2文字：${name.SubString(0,2)}
```
```C#:コンテキスト
context.Put("name", "あいうえお")
```
```text:生成結果
名前の長さ：5
名前の長さ：5
名前の先頭2文字：あい
```

### if 構文 ###

C# の if とほぼ同じです。

```text:テンプレート
-1-
#if ($name.SubString(0,1) == "あ")
"あ"で始まる
#end
-2-
#if ($name.SubString(0,1) == "か")
"か"で始まる
#end
-3-
#if ($name.SubString(0,1) == "さ")
"さ"で始まる
#elseif ($name.SubString(0,1) == "あ")
"あ"で始まる
#else
不一致
#end
-4-
```
```C#:コンテキスト
context.Put("name", "あいうえお")
```
```text:生成結果
-1-
"あ"で始まる
-2-
-3-
"あ"で始まる
-4-
```

### foreach 構文 ###

C# の for each とほぼ同じです。
$velocityCount でループカウンタの値を取得することができます。1 オリジンです。
0 オリジンのカウンタが必要である場合、set 構文を用いて演算した結果を出力します。

```text:テンプレート
#foreach ($c in ${name})
[${velocityCount}] ${c}
#end

#set ($i=0)
#foreach ($c in ${name})
#set ($i=${velocityCount} - 1)
[${i}] ${c}
#end
```
```C#:コンテキスト
context.Put("name", "あいうえお")
```
```text:生成結果
[1] あ
[2] い
[3] う
[4] え
[5] お

[0] あ
[1] い
[2] う
[3] え
[4] お
```

カウンタ変数を用いた for ループを行いたい場合、配列を使用して次のように記述します。[0..4] は 0 ～ 4 の配列を表します。

```text:テンプレート
#foreach ($i in [0..4])
[${i}]
#end
```
```text:生成結果
[0]
[1]
[2]
[3]
[4]
```

### コメント ###

単一行コメントは ## です。
複数行コメントは #* *# で囲みます。

```text:テンプレート
## 単一行コメント
あいうえお ## 文末コメント
#*
複数行コメント
複数行コメント
*#
あいうえお #* 文中コメント *# かきくけこ
```
```text:生成結果
　
あいうえお 




あいうえお  かきくけこ
```