テンプレートを変更した訳でもないのに,今日になって突然再構築に失敗するようになってしまった。原因は去年の記事のタイトルだった。
■ ■ ■
今日,Movable Type でメインインデックスを再構築しようとすると,見たことのないエラーで失敗するようになってしまった。テンプレートもソースも変更していないのに,突然そうなった。次のエラーメッセージが表示される。今までに見たことのないメッセージである。Perl が出しているメッセージのようだ。
An error occurred:
テンプレート 'Main Index' の作成に失敗しました:
MT::App::CMS=HASH(0x8ed1410) Bareword found where operator expected at (eval 1576) line 8, near "'2004:
環境は,Movable Type 2.661,Perl 5.8.2,関連プラグインは,Brad Choate: MTOnThisDay,Brad Choate: PerlScript Plugin である。
エラーメッセージの内容で見当がつかない場合,有効なのはコマンドラインからの再構築である。それには mt-rebuild を使う (nlog(n): cron でインデックスを再構築)。mt-rebuild でメインインデックスの再構築を行った結果は次ようになった。
$ mt-rebuild.pl -mode="index" -blog_id=1 -template="Main Index"
Bareword found where operator expected at (eval 12) line 8, near "'<a href="http://nlogn.ath.cx/archives/2004_12_24.html" title="2004年12月24日"><strong>2004:</strong></a><br /><a href="http://nlogn.ath.cx/archives/000358.html" title="X'mas"
(Missing operator before mas?)
Unquoted string "mas" may clash with future reserved word at (eval 12) line 8.
Rebuild error: Build error in template 'Main Index': Error in <MTPerlScript> tag: Error in PerlScript tag: Unrecognized character \xA4 at (eval 12) line 8.
「mas」が引用符にくくられていない旨のメッセージが表示されている。原因は,記事番号 000358 の,タイトルが「X'mas ではなく Xmas」の記事である。これはちょうど1年前の今日書いた記事である。メインインデックスには,1年前の記事を MTOnThisDay プラグインを使って表示している。これが原因である。テンプレートは次のようになっている (nlog(n): おかげさまで1周年 - 去年の今日を表示する)。
<div class="sidetitle">
On This Day
</div>
<div class="side">
<MTPerlScript>
$a = '<MTOnThisDay><MTEntries days="1"><MTDateHeader><a href="<$MTEntryLink archive_type="Daily"$>" title="<$MTEntryDate format="%x" language="jp"$>"><strong><$MTEntryDate format="%Y"$>:</strong></a><br /></MTDateHeader><a href="<$MTEntryLink$>" title="<$MTEntryTitle$>"><$MTEntryTitle$></a><br /></MTEntries></MTOnThisDay>';
if ($a =~ /\S/) { print "$a"; } else { print "no entries"; }
</MTPerlScript>
</div>
このままだと構造が分かりにくいので,概要を書くと次のようになる。
<MTPerlScript>
$a = '(MTOnThisDay の出力)';
if ($a =~ /\S/) { print "$a"; } else { print "no entries"; }
</MTPerlScript>
$a に MTOnThisDay の出力を代入し,$a が空でなかったらその文字列を表示し,$a が空だったら「no entries」を表示するようになっている。この場合分けは MTOnThisDay だけではできないので,PerlScript プラグインを使っている。
問題は,1年前の記事のタイトルが「X'mas ではなく Xmas」だったことである。アポストロフィ「'」がタイトルに含まれている。これは単一引用符でもあるので,$a に代入する文字列に単一引用符が含まれていると,文字列がそこで終わってしまう。すると,Perl はそれに続く「mas」は文字列以外として扱うために,意味を解釈できずエラーを出すことになる。このエラーが上記のエラーである。
解決方法は,「'」を単一引用符でなくせばよい。文字実体参照「'」で表現すれば,HTML のソースでは「'」となり,Web ブラウザでは「「'」と表示される。このように出力するには,<$MTEntryTitle$> を <$MTEntryTitle encode_xml="1"$> に書き換えればよい(Movable Typeユーザー・マニュアル: テンプレート・ タグ - グローバル・タグ・アトリビュート)。
<div class="sidetitle">
On This Day
</div>
<div class="side">
<MTPerlScript>
$a = '<MTOnThisDay><MTEntries days="1"><MTDateHeader><a href="<$MTEntryLink archive_type="Daily"$>" title="<$MTEntryDate format="%x" language="jp"$>"><strong><$MTEntryDate format="%Y"$>:</strong></a><br /></MTDateHeader><a href="<$MTEntryLink$>" title="<$MTEntryTitle encode_xml="1"$>"><$MTEntryTitle encode_xml="1"$></a><br /></MTEntries></MTOnThisDay>';
if ($a =~ /\S/) { print "$a"; } else { print "no entries"; }
</MTPerlScript>
</div>
トラックバックやコメントは他のサイトから飛んでくるので,「encode_xml="1"」をつけていたが,タイトルは自分でつけるのでこのようなことはないと思っていた。落とし穴だった。
PerlScript プラグインを使っていない場合は,このような問題は発生しない。
2006年1月28日追記:
encode_xml 属性はつけない方がいいということが分かりました。「'」は手入力で「'」とした方がいいです(nlog(n): encode_xml 属性の扱いの難しさ)。
<div class="sidetitle">
On This Day
</div>
<div class="side">
<MTPerlScript>
$a = '<MTOnThisDay><MTEntries days="1"><MTDateHeader><a href="<$MTEntryLink archive_type="Daily"$>" title="<$MTEntryDate format="%x" language="jp"$>"><strong><$MTEntryDate format="%Y"$>:</strong></a><br /></MTDateHeader><a href="<$MTEntryLink$>" title="<$MTEntryTitle$>"><$MTEntryTitle$></a><br /></MTEntries></MTOnThisDay>';
if ($a =~ /\S/) { print "$a"; } else { print "no entries"; }
</MTPerlScript>
</div>
Posted by n at 2005-12-24 22:52 | Edit | Comments (0) | Trackback(0)