Movable TypeでCSVデータからtable要素を作る方法
Movable Typeを使って、CSVデータからtable要素を簡単に作る方法を紹介します。このエントリーはMTQに寄せられたご質問の回答を情報展開したものです。
1.カスタマイズイメージ
次のようなカンマ区切りのCSVデータをブログ記事の本文に記述します。
h1,h2,h3,h4,h5
a1,a2,a3,a4,a5
b1,b2,b3,b4,b5
c1,c2,c3,c4,c5
このデータから次のtable要素を生成します。
<table>
<thead>
<tr><th>h1</th><th>h2</th><th>h3</th><th>h4</th><th>h5</th></tr>
</thead>
<tbody>
<tr><td>a1</td><td>a2</td><td>a3</td><td>a4</td><td>a5</td></tr>
<tr><td>b1</td><td>b2</td><td>b3</td><td>b4</td><td>b5</td></tr>
<tr><td>c1</td><td>c2</td><td>c3</td><td>c4</td><td>c5</td></tr>
</tbody>
</table>
2.カスタマイズ
CSVデータを分解するにはSplitプラグインを利用します。
プラグインをインストールした後、次のサブテンプレートをインデックステンプレートに記述して、再構築またはプレビューを実行します。サンプルは一番外側のMTEntriesタグにidモディファイアを与えて、ブログ記事IDが「100」の本文だけを処理するようにしています。
<mt:Entries id="100">
<table>
<mt:EntryBody split="\n" setvar="foo">
<mt:loop name="foo">
<mt:GetVar name="__value__" split="," setvar="bar" />
<mt:if name="__first__">
<thead>
<mt:loop name="bar">
<mt:if name="__first__">
<tr>
</mt:if>
<th><mt:GetVar name="__value__" /></th>
<mt:if name="__last__">
</tr>
</mt:if>
</mt:loop>
</thead>
<mt:else>
<mt:if "__counter__" eq="2">
<tbody>
</mt:if>
<mt:loop name="bar">
<mt:if name="__first__">
<tr>
</mt:if>
<td><mt:getVar name="__value__" /></td>
<mt:if name="__last__">
</tr>
</mt:if>
</mt:loop>
</mt:if>
</mt:loop>
</tbody>
</table>
</mt:Entries>
MTEntriesタグでブログ記事を読み込むだけでなく、同じインデックステンプレートにMTSetVarBlockタグでCSVデータを記述し、その変数を読み込むという方法もあります。
3.テンプレートの解説
MTEntryBodyタグで本文(CSVデータ)を取得し、splitモディファイアで改行文字(¥n)をセパレータにして分割した結果を変数fooに保持します。
<mt:EntryBody split="\n" setvar="foo">
変数fooには配列で各行のデータが保存されます。イメージは次のような感じです。
$foo[0] = 'h1,h2,h3,h4,h5'
$foo[1] = 'a1,a2,a3,a4,a5'
$foo[2] = 'b1,b2,b3,b4,b5'
$foo[3] = 'c1,c2,c3,c4,c5'
最初のMTLoopタグでこの変数fooを処理します。1回目の繰り返しでは「'h1,h2,h3,h4,h5'」、2回目の繰り返しでは「'a1,a2,a3,a4,a5'」という順で処理を行っていきます。
<mt:loop name="foo">
…中略…
</mt:loop>
1回目の繰り返し処理の中で、MTGetVarタグを使って変数fooから「__value__」で値「'h1,h2,h3,h4,h5'」を取得し、その値をsplitモディファイアでカンマ文字をセパレータにして、分割した結果を変数barに保持します。
<mt:GetVar name="__value__" split="," setvar="bar" />
変数barにはカンマで区切ったデータが配列で保存されます。イメージは次のような感じです。
$bar[0] = 'h1'
$bar[1] = 'h2'
$bar[2] = 'h3'
$bar[3] = 'h4'
$bar[4] = 'h5'
次のMTIfタグでは、繰り返し処理が初回か初回でないかを判定しています。これは初回の場合はthead要素とth要素を出力し、2回目以降はtbodyとtd要素を出力させるためです。
<mt:if name="__first__">
(thead要素とth要素を出力)
<mt:else>
(tbody要素とtd要素を出力)
</mt:if>
初回の繰り返しの場合は次の処理を行います。MTLoopタグでは先程カンマで分割した配列変数barを処理します。繰り返しの初回でtr要素の開始タグを出力し、MTGetVarタグで値(h1~h5)を順番に出力します。繰り返しの最後でtr要素の終了タグを出力します。
<mt:if name="__first__">
<thead>
<mt:loop name="bar">
<mt:if name="__first__">
<tr>
</mt:if>
<th><mt:GetVar name="__value__" /></th>
<mt:if name="__last__">
</tr>
</mt:if>
</mt:loop>
</thead>
2回目以降の繰り返しの場合は次の処理を行います。MTIfタグで2回目の繰り返しの場合のみtbody要素を出力します。tbodyの終了タグはすべての処理の最後に出力すればよいのでここでは登場しません。
あとは先程と同様、MTLoopタグではカンマで分割した配列変数barを処理します。繰り返しの初回でtr要素の開始タグを出力し、MTGetVarタグで値(a1~a5/b1~b5/c1~c5)を順番に出力します。
<mt:else>
<mt:if "__counter__" eq="2">
<tbody>
</mt:if>
<mt:loop name="bar">
<mt:if name="__first__">
<tr>
</mt:if>
<td><mt:getVar name="__value__" /></td>
<mt:if name="__last__">
</tr>
</mt:if>
</mt:loop>
その他、次のように最初のMTLoopで1行分のデータを別々の変数に保持してから出力するという方法もあります。こちらの方が見通しはよいですが、CSVデータの増減に柔軟に対応できるのは前述のサブテンプレートです。
<mt:Entries id="100">
<mt:EntryBody split="\n" setvar="foo">
<table>
<mt:loop name="foo">
<mt:GetVar name="__value__" split="," setvar="bar" />
<mt:loop name="bar">
<mt:if name="__counter__" eq="1"><mt:GetVar name="__value__" setvar="data1" /></mt:if>
<mt:if name="__counter__" eq="2"><mt:GetVar name="__value__" setvar="data2" /></mt:if>
<mt:if name="__counter__" eq="3"><mt:GetVar name="__value__" setvar="data3" /></mt:if>
<mt:if name="__counter__" eq="4"><mt:GetVar name="__value__" setvar="data4" /></mt:if>
<mt:if name="__counter__" eq="5"><mt:GetVar name="__value__" setvar="data5" /></mt:if>
</mt:loop>
<mt:if name="__first__">
<thead>
<tr>
<th><mt:GetVar name="data1" /></th>
<th><mt:GetVar name="data2" /></th>
<th><mt:GetVar name="data3" /></th>
<th><mt:GetVar name="data4" /></th>
<th><mt:GetVar name="data5" /></th>
</tr>
</thead>
<mt:else>
<mt:if name="__counter__" eq="2">
<tbody>
</mt:if>
<tr>
<td><mt:GetVar name="data2" /></td>
<td><mt:GetVar name="data3" /></td>
<td><mt:GetVar name="data4" /></td>
<td><mt:GetVar name="data5" /></td>
</tr>
</mt:if>
</mt:loop>
</tbody>
</table>
</mt:Entries>
4.区切り文字について
splitモディファイアの区切り文字にはタブ(¥t)を指定することも可能です。任意の文字列を設定すれば、それがそのまま区切り文字となります。
5.注意事項
WindowsにインストールしたMTでは、splitタグによる正常な動作を確認できていません。
- Movable Type検索結果画面のMTIncludeタグでファイルを読み込む方法
- Movable Typeの月別コンテンツアーカイブリスト用テンプレート
- コンテンツデータでMTEntriesWithSubCategoriesの代替テンプレートタグ
- MTContentFieldタグの使い方
- Movable Typeでブログ記事一覧をカスタムフィールドでソートする方法
- MTの本文フィールドからimg要素のURLを取得する方法
- MTEntriesタグで指定した数の記事を除外して表示する方法
- Movable Typeのテンプレートタグの中でテンプレートタグを使う方法
- Movable Typeのテンプレートタグをテンプレートで生成する方法
- Movable TypeのMTEntriesタグで特定の複数ブログ記事を出力する方法
- MTIncludeタグのnameモディファイア
- Movable Type(MT)の特殊変数の入れ子
- ブロックタグにelseタグを組み込んで判定する
- Movable Type 5 におけるウェブサイトとブログの複数指定方法
- ウェブサイトとブログでグローバルナビゲーションを共有する