第27回 実体における文字符号化の問題を整理する Page 3

川俣 晶
株式会社ピーデー
2004/11/18

Byte Order Markをめぐる根深い問題

 さて、次は「Byte Order Mark」、通称BOMの話題である。BOMを付ける、付けないに関してはさまざまな流儀があり、混乱が見られるため、規定が必要とされる。

Entities encoded in UTF-16 MUST and entities encoded in UTF-8 MAY begin with the Byte Order Mark described by Annex H of [ISO/IEC 10646:2000], section 2.4 of [Unicode], and section 2.7 of [Unicode3] (the ZERO WIDTH NO-BREAK SPACE character, #xFEFF). This is an encoding signature, not part of either the markup or the character data of the XML document. XML processors MUST be able to use this character to differentiate between UTF-8 and UTF-16 encoded documents.

UTF-16で符号化した実体は、[ISO/IEC 10646:2000]の附属書H,[Unicode]の2.4, [Unicode3]の2.7で規定するマーク(ZERO WIDTH NO-BREAK SPACE文字、#xFEFF)で始まらなければならず、UTF-8で符号化した実体は、マークで始まってもよい。これは、符号化のマークであって、XML文書のマーク付けの一部でも、文字データの一部でもない。XMLプロセサは、この文字を使用して、UTF-8で符号化した文書とUTF-16で符号化した文書との区別を行えなければならない。

 冒頭の文章の本題はマークにあるのだが、その前にこの文章の対象を確認しておこう。この文章の主語は、「UTF-16で符号化した実体」や「UTF-8で符号化した実体」である。前の段落のように、「外部解析対象実体」とは書かれていない。つまり、この段落は文書実体も対象に含むと考えるべきだろう。

 では本題に入ろう。このマークは、UnicodeとISO/IEC 10646で扱いが微妙に異なる困った代物である。このマークの存在意義は、文字符号化スキームの種類と、エンディアンの自動判定にある。Unicodeは、既存の文字符号化スキームの世代交代として使われる以上、旧文字符号化スキーム体系との混在状況があり得る。そのため、Unicodeか旧文字符号化スキームかを自動判定する仕組みが必要とされる。また、Unicodeはビッグエンディアンとリトルエンディアンの双方を許容している。これらは、複数バイトから構成されるデータを、上位バイトから先に記述するか、下位バイトから先に記述するかの点で異なる。つまり、エンディアンを間違って処理するとまったく意味のないデータを処理することになってしまう。マークとはこれを判定するために付加されるマークのことである。マークであって、文字ではない。これを「BOM」(Byte Order Mark)という。

 しかし、ISO/IEC10646では、この仕様を踏襲せず、これに幅がゼロで分割しない空白文字(ZEROWIDTH NO-BREAK SPACE character)という名前を付け、文字扱いしてしまった(厳密には、ISO/IEC 10646でもマークとして扱う場合もあるのだが、ここではあえて正しくはないが、ZERO WIDTH NO-BREAK SPACE characterは常に文字を示すということで話を進める)。それだけではない。

 さらにややこしいのは、読み込んだコードがByte Order MarkであるかZERO WIDTH NO-BREAK SPACE characterであるか区別できないケースがあることだ。どちらも、ビット列で見ればまったく同じであるし、UTF-16というような文字符号化スキームの名前だけでは、どちらを使っているかは区別できない。

 そして、区別できないことは、さらなる悪夢を招く。Byte Order Markはマークであって文字ではないが、ZERO WIDTH NO-BREAKSPACE characterは文字である。もし、XML文書の先頭にByte Order Markが付加されていた場合、これは文字ではないので、EBNFで記述された生成規則で判定する対象にならない。つまり、Byte Order MarkがあってもXML文書の解析(パース)には影響を及ぼさない。しかし、ZERO WIDTH NO-BREAK SPACE characterは文字であるため、それはEBNFで記述された生成規則による判定の対象になってくる(EBNFの詳細については、第2回「XML勧告読解に必須のEBNF」を参照)。

 XML文書の先頭にZERO WIDTH NO-BREAK SPACE characterが付加されていた場合、生成規則[1] documentをたどってみると、XML文書の先頭にZERO WIDTH NO-BREAK SPACE characterの記述が許されるケースが1つもないことが分かるだろう。もし、XML宣言が記述される場合は、先頭は「<」になり、ZERO WIDTHNO-BREAK SPACE characterになることはできない。それが省略されたケースでは、コメント、処理命令、空白文字、文書型宣言、要素のいずれかが先頭に来ることになる。このうち、空白文字以外のすべてはやはり先頭が「<」になる。空白文字で許されるのは、#x20(半角空白)、#x9(タブ)、#xD(復帰)、#xA(改行)だけなので、やはりZERO WIDTH NO-BREAK SPACE characterは含まれない。

 その結果、XML文書の先頭にZERO WIDTH NO-BREAK SPACE characterが付加されている場合、それはXML文書としては誤りということになる。つまり、XML文書の先頭のあるコードがByte Order MarkともZERO WIDTH NO-BREAK SPACE characterとも見なせる場合、前者として解釈すると解析できるのに、後者として解釈すると誤りになるというケースの発生が考えられる。

 話を戻そう。このような混迷は、この段落の規定により回避される。最初の文章は、UTF-16で記述した実体には、必ずこのマークを付けるとしている。つまり、UTF-16で記述した実体の先頭に付加されているものは必ずマークと解釈でき、文字とは解釈されない。また、UTF-8で記述した実体はこのマークを持ってもよい、としている。この文章はあいまいであるかのように見える。マークを持ってもよい、ということは、マークを持たないという選択もあるという意味である。ならば、先頭にもZERO WIDTH NO-BREAK SPACE characterを文字として書いてもよいことになる。そのようなXML文書は、XMLプロセッサによって誤りと見なされてしまうのだろうか。おそらく、そうではないだろう。Byte Order MarkとZERO WIDTH NO-BREAK SPACE characterは区別できないので、UTF-8で記述した実体はこのマークを持ってもよい、という規定により、これはマークとして処理されてしまうことになり、エラーにならないと思われる。

 次の文章は、マークと文字のあいまいさを取り除くための規定といえる。つまり、これらはマークであって文字ではなく、マーク付けや文字データの一部になることはない、ということである。

 最後の文章は、XML宣言を付けなくても、マークだけでUTF-16とUTF-8の区別を付ける能力をXMLプロセサは持たねばならないということである。区別する方法の詳細は、「F Autodetection of Character Encodings(F 文字符号化の自動検出)」に記述されているので、ここでは触れないことにする。取りあえず上記の説明に、マークがないときにはUTF-8と見なす、というヒントを足せば、区別可能であることが推測できると思う。

 さて、まだ「4.3.3 Character Encoding in Entities(4.3.3 実体における文字符号化)」の途中であるが、今回はここまでである。今回読んだ規定のかなりの部分は、文字に関する標準が明確に確立していれば、なくてもよかったものである。しかし、文字にまつわる問題は根深い。昔からある機種依存文字の問題もその1つだが、混乱を収束させることが重要な目的の1つであるはずのISO 10646/Unicodeも、Byte Order MarkとZERO WIDTH NO-BREAK SPACE characterという新たな混乱の発生源になっている。標準には技術的といよりは政治的というべき闘争が付き物であるが、特に文字コード関係にはそれが顕著に見られるように思われる。明らかに無理がある標準を、何とか筋が通るように整合させる処理に携わった方々の話を聞く機会が何回かあったが、まさにきれい事では済まない世界である。故に、XMLのような高い相互運用性を目的とする技術では、どうしても文字に関する多くの規定を含める必要性が発生してしまうのが現状なのである。

 なぜXMLを使うのかという理由はいろいろあるが、このような文字に関する混乱をある程度収束させ、相互運用性が向上するから、という主張もあり得るような気がする。

 次回は「4.3.3 Character Encoding in Entities(4.3.3 実体における文字符号化)」を最後まで読み切ってしまおう。XML宣言の中に記述される「encodeing="……"」という部分に当たる符号化宣言などについて読む。XMLに入門する初心者が誰でも一度は書いてみる構文なので、多くの読者が親しみを持てるのではないかと思う。(次回に続く)

3/3

 Index
やさしく読む「XML 1.0勧告」 第27回
実体における文字符号化の問題を整理する
  Page 1
・実体における文字符号化の概要
・実体における文字符号化
  Page 2
・外部解析対象実体の文字符号化
Page 3
・Byte Order Markをめぐる根深い問題


連載 やさしく読む「XML 1.0勧告」


XML & SOA フォーラム 新着記事
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

HTML5+UX 記事ランキング

本日月間