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

読了まで:約3分


blosxom の自作記法系プラグイン nyarlax を書き直ししていたときに、& を含む文字列どう処理するかによって、エントリの内容が変わってしまう問題に直面しました。

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

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

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

何が問題か

いったい何が問題でどういう場合問題が起きるのかというと、 (X)HTML や XML に CGI などでプログラムコードを出力 ときに、

プログラムコードの内容が変わってしまう ということが起きます。

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

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

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

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

のようになってしまいます。

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

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

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

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

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

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

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

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

そうするには、

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

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

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

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

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

解決策の例

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

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

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

最後に

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

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

おまけ

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

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


追記: [[2018-02-22]] この記事は 2006 年に僕がブログ始めた当初の記事です。

にゃるら(カラクリスタ)

『輝かしい青春』なんて失かった人。
次に備えて待機中。

今は趣味でプログラミングをして
生活しています。