MTTopLevelCategories/MTSubCategoriesタグでglueモディファイアと同様の処理を行う

MTQに以下のような質問が上がっていました。

MTsubCategoriesには glue が無いようなのですが、同等の事を可能にする方法があればご教授いただきたくお願い申し上げます。

この質問に答えてみます。

1.MTSubCatIsLastタグを使う

MTQですでに解答されていますが、同一の親を持つカテゴリの中で、カテゴリの間にglueを出力するには、以下のようにすれば良いです。

<mt:SubCategoriesまたはmt:TopLevelCategories>
  カテゴリの情報を出力
  <mt:SubCatIsLast>
  <mt:Else>
    glueの文字列
  </mt:SubCatIsLast>
</mt:SubCategoriesまたはmt:TopLevelCategories>

MTSubCatIsLastタグは、同一の親を持つカテゴリの中で、最後のカテゴリの時だけ処理を行うブロックタグです。
また、MTElseタグは、条件を満たさない時の処理を指定するタグです。

上記のテンプレートでは、最後のカテゴリの時には何も出力せず、それ以外の時にはglueの文字列を出力しています。
結果として、同一の親を持つカテゴリの中では、それぞれのカテゴリの間にglueが出力されます。

2.すべてのカテゴリを対象にする

質問された方の要望は、同一の親を持つカテゴリの中でのglueではなく、MTTopLevelCategories/MTSubCategoriesタグで出力するすべてのカテゴリを対象に、カテゴリの間にglueを出力するというものです。
この場合は、MTSubCatIsLastタグを使う方法では処理できません。

そこで、以下のような方法を考えてみました。

  • 1.それぞれのカテゴリの情報を出力する際に、glueの文字列も出力します。
  • 2.正規表現を使って、最後に出力されたglueの文字列を削除します。

テンプレートを組むと、以下のようになります。

<mt:SetVarBlock name="cats">
<mt:SubCategoriesまたはmt:TopLevelCategories>
  カテゴリの情報を出力
  glueの文字列
  <$mt:SubCatsRecurse$>
</mt:SubCategoriesまたはmt:TopLevelCategories>
</mt:SetVarBlock>
<$mt:GetVar name="cats" regex_replace="/(.*)glueの文字列(.*?)$/s","$1$2"$>

1~7行目で、カテゴリの情報とglueからHTMLを組み立て、変数catsに代入します。
そして、8行目の正規表現で、変数catsの値に対してregex_replaceモディファイアで正規表現で置換を行い、最後に出力したglueを削除します。

上の正規表現の「/(.*)glueの文字列(.*?)$/s」は、以下のような意味になっています。

正規表現意味
(.*)0文字以上のできるだけ長い文字列にマッチさせ、それをメモリに記憶する
(.*?)0文字以上のできるだけ短い文字列にマッチさせ、それをメモリに記憶する
最後の方の「$」文字列の最後にマッチさせる
最後の「s」「.」を改行文字にもマッチさせる

「できるだけ長い文字列」と「できるだけ短い文字列」→「文字列の最後」の間に、glueの文字列を挟んでいます。
そのため、変数catsの値を、一番最後に出現するglueの文字列で区切って、その前とその後ろを(=一番最後のglueを除いた部分)を、メモリに記憶する動作になります。

また、正規表現の後半の「$1$2」は、1番目にメモリに記憶した内容($1)と、2番目にメモリに記憶した内容($2)を出力することを意味します。
結果として、最後のglueを除いた文字列を出力することができます。