カラクリサイクル

『輝かしい青春』なんて失かった人の雑記

&を含む文字列の処理問題

概要: blosxomの自作記法系プラグイン nyarlax を書き直ししていたときに、


&を含む文字列どう処理するかによって、エントリの内容が変わってしまう問題に 直面しました。

というかしばらく前のエントリマークアップがおかしい件 でも同じことが原因になってるわけですが。

Wikiやその他Blogツールの独自記法系プラグインにも同じ問題が含まれているような気がするので、 問題点を整理する意味でもまとめてみるエントリ。

ちなみに例になっているコードは全部Perlです。

何が問題か

いったい何が問題でどういう場合問題が起きるのかというと、 (X)HTMLXMLにCGIなどでプログラムコードを出力ときに プログラムコードの内容が変わってしまうということが起きます。

例えば以下のコードを貼り付けたいとします。

my $str = '&の問題';
$str =~ s/&/&/g;

しかし、処理の仕方によっては、

my $str = '&の問題';
$str =~ s/&/&/g;

のようになってしまいます。なにがどう変わってんの?というと &&になってしまっています。

何故こんなことが起きるのか

上記の問題は以下のコードのような処理を行っていると起こりえます。

# 例1
my $str = '&を含む<文字列>';
$str =~ s/&/&/g;                     # &     => &
$str =~ s/&/&/g;                     # &         => &
$str =~ s/&(\w+);/&$1;/g;            # >  => >
$str =~ s/&#(\d+);/&#$1;/g;          #  => 
$str =~ s/&#x([a-f0-9]+);/&#x$1;/ig; # &#x2f => /
# $str = '&を含む<文字列>' となる。

上記のコードのような処理では&という文字列を出力したい場合&と書くことになります。 ようするに&&と書く必要があるわけです。(X)HTMLなんかに貼り付ける場合はそうなります。

が、これはめんどくさい。少なくともCGIなんかで処理する場合はこの手間は省きたいわけです。

あちらが立てばこちらが立たず

じゃあ、一般実体参照数字文字参照として扱わされないようにすればいいじゃないと思うわけです。

そうするには、

# 例2
my $str = '&を含む<文字列>';
$str =~ s/&/&/g; # &         => &
# $str = '&を含む<文字列>' となる。

こんな感じにします。しかし、これだと今度は一般実体参照数字文字参照 が使えなくなってしまいます

&を含む文字列、一般実体参照数字文字参照をどう表示したいのか

問題は要するに、一般実体参照や数字文字参照を単なる文字列として扱いたいのか、 それとも一般実体参照や数字文字参照そのものとして扱いたいのか、ということになります。

プログラムコードであれば前者、普通の文章ならば後者になるわけです。で、実際実装する場合 このあたり考えないと面倒なことになります。というかこの問題どうするか考えるのが面倒だったりしますが。

解決策の例

プログラムコードに前者(単なる文字列として扱う)を適用し、 普通の文章に後者(一般実体参照や数字文字参照そのものとして扱う)を適用する、という実装でもいいと思うんですが、 記法によって扱いが変わる、というのは若干ややこしい気がするので、別の方法を考えてみます。というか 自分のところの実装方法だったりします。

どう言う実装かと言うと、基本的に&&に変換し&そのものを出力するにはバックスラッシュ(**)でエスケープする と言う感じになってます。要は、&と書くと&が出力されるという感じ。

ただ、この方法は自分ひとりだけが使う場合いいんですが、第三者が使う場合微妙な気がします。

最後に

文章がおかしいとかわかりづらいとかここは間違っているとかがあったら、 コメントなりトラックバックなりで指摘してください。というか自分でも若干こんがらがってます。 最初なにがどうなってるのかよく分かってませんでした。今でもそうですが。

ようするに&とかを処理しつつ&とかを扱うのはややこしいという話。 こんがらがっているのは自分だけかもしれませんが。

おまけ

そういえば、このBlog(空繰再繰)にアイコン(正確にはfaviconですが)をつけました。 なかなかいい感じ。faviconに対応しているブラウザだと表示されます。

あとIE6(=Internet Explorer 6)でサイドバーが落ちてるのをとりあえず直しました。 が、あのCSSはひどいような。IE6にしか適用されないようになってるけど。