第37回 文字符号化方式にまつわるジレンマ Page 3

川俣 晶
株式会社ピーデー
2005/9/13

外部の符号化情報がない場合の検出

 さて、2つのケースの1つ目、「F.1 Detection Without External Encoding Information(F.1 外部の符号化情報がない場合の検出)」である。「外部の符号化情報がない場合」とは、XML文書本体そのものと、そこに含まれる符号化宣言だけを手掛かりに符号化方式を確定する場合である。

 では、早速読んでいこう。

Because each XML entity not accompanied by external encoding information and not in UTF-8 or UTF-16 encoding must begin with an XML encoding declaration, in which the first characters must be '<?xml', any conforming processor can detect, after two to four octets of input, which of the following cases apply. In reading this list, it may help to know that in UCS-4, '<' is "#x0000003C" and '?' is "#x0000003F", and the Byte Order Mark required of UTF-16 data streams is "#xFEFF". The notation ## is used to denote any byte value except that two consecutive ##s cannot be both 00.
外部の符号化情報を伴わず、UTF-8またはUTF-16符号化ではないXML実体は、最初の文字列を'<?xml'とするXML符号化宣言で始めなければならないので、どの適合したプロセサも、入力にある2オクテットまたは4オクテットを調べれば、附属書F表1、表2に示すどの場合があてはまるかを検出できる。このリストを読む際には、UCS-4の'<'が"#x0000003C"、'?'が"#x0000003F"、およびUTF-16のデータストリームの必要とする“印”(しるし=Byte Order Mark)が"#xFEFF"ということを知っておくと役立つ。##記法は任意のバイト値を表すが、連続する2つの##が両方とも00であることはないという例外がある。

 XML勧告本文中に、外部の符号化情報を伴わず、UTF-8またはUTF-16符号化ではないXML実体の最初の文字列は

上位のプロトコルによって符号化が決まらない場合、符号化宣言を含まないXML実体が、正しいUTF-8またはUTF-16の内容を持たないときも、致命的な誤りとする。

とある。つまり、「外部の符号化情報をともなわず、UTF-8またはUTF-16符号化ではないXML実体は符号化宣言を含む」という規定は存在することになる。そして、「符号化宣言を含む」ということは、それを記述するためにXML宣言またはテキスト宣言が存在しなければならず、どちらも文書の先頭に書くことが必須の要求である。そして、どちらも、書き始めは「<?xml」という共通点を持つ。これらを含めて考えれば、書き出しは常に「<?xml」ということになる。

 次の前2者は通常の文字に対するコードである。後者は、いわゆるBOM(Byte Order Mark)であるが、もちろんUCS-4でこれが使用される場合がある。ただ、UCSではBOMという名前を使わず、“ZERO WIDTH NON-BREAKING SPACE”と呼んでいるためBOMと呼ばれることがないというだけの話である。つまり、UCS-4で「印」が付くことはあり得、それは表中に反映されている。またUTF-8でも使用される場合がある。

 次にある例外は、UTF-16、big-endian、UCS-4、unusual octet order(3412)の2つを適切に区別するために必須の条件といえる。もし、この例外がなければ、FE FF 00 00というオクテット(Octet=8bitのこと)列を受け取った場合、どちらの条件にもマッチするということになり、区別できない。

 次は、Byte Order Markがある場合についての表である。

With a Byte Order Mark:

00 00 FE FF UCS-4, big-endian machine (1234 order)
FF FE 00 00 UCS-4, little-endian machine (4321 order)
00 00 FF FE UCS-4, unusual octet order (2143)
FE FF 00 00 UCS-4, unusual octet order (3412)
FE FF ## ## UTF-16, big-endian
FF FE ## ## UTF-16, little-endian
EF BB BF UTF-8

 この表は、入力されたオクテットの列が、左側に書かれたとおりの場合、右側に書かれた符号化方式であると確定できることを意味する。ちなみに、big-endianとは、上位バイトを先に書くやり方であり、little-endianは下位バイトを先に書くやり方である。Intelのx86プロセッサはlittle-endianを採用しているが、これと互換性のないCPUの中には、big-endianを採用しているものがある(例えば、モトローラの68で始まる型番の一連のマイクロプロセッサなど)。little-endianのCPUでは、little-endianのUTF-16を使う方が効率が良く、big-endianのCPUでは、big-endianのUTF-16を使う方が効率が良いために、双方が許されている。little-endianとbig-endianの違いがバイト順(Byte Order)であり、Byte Order Markとはその名のとおり、もともとはこの2つを区別する印(Mark)として生まれたものである。

 もう1つ、UCS-4の「1234 order」などの表記も説明しておこう。UCS-4は4オクテット(4バイト)で(不正確な表現ではあるが)1文字を表現する。つまり、文字番号を示すコードが4バイトで構成されるということである。通常は、big-endian(上から1、2、3、4の順にバイトを書く、つまり「1234 order」)か、あるいはlittle-endian(上から4、3、2、1の順にバイトを書く、つまり「4321 order」)となる。しかし、16bit単位で処理するシステムをそれと意識することなく通した場合に、2、1、4、3や3、4、1、2といった普通ではないオクテット順(unusual octet order)になる可能性が考えられる。どのようなシステムでこのようなオクテット順になるか、残念ながら筆者は知らないのだが、XML勧告はそのケースも想定して記述されている。

 最後に、UTF-8のケースだけ補足しておこう。UTF-8のEF BB BFという3バイト(3オクテット)の並びは、#xFEFFというByte Order MarkをUTF-8の表記に置き換えたものである。UTF-8にはbig-endianもlittle-endianもなく、1種類しか存在しない。それにもかかわらず、Byte Order Markを付けるのは、それがUTF-8であるという自動識別をやりやすくするためである。実際、UTF-8のByte Order Markは、同じ番号であるにもかかわらず、バイト列(オクテット列)として見た場合にUTF-16と異なり、容易に識別できる。

 次は、Byte Order Markなしの場合の表である。Byte Order Markには賛否両論があり、これを付けるべきではないという意見も根強い。また、Byte Order MarkはUnicode系の世界でのみ意味のあるコードであり、US-ASCIIやシフトJISではもちろん付けたくても付けようがない。Byte Order Markが付いていないというケースも十分に検討しておく価値がある。

Without a Byte Order Mark:

00 00 00 3C UCS-4 or other encoding with a 32-bit code unit and ASCII characters encoded as ASCII values, in respectively big-endian (1234), little-endian (4321) and two unusual byte orders (2143 and 3412). The encoding declaration must be read to determine which of UCS-4 or other supported 32-bit encodings applies.
3C 00 00 00
00 00 3C 00
00 3C 00 00
00 3C 00 3F UTF-16BE or big-endian ISO-10646-UCS-2 or other encoding with a 16-bit code unit in big-endian order and ASCII characters encoded as ASCII values (the encoding declaration must be read to determine which)
3C 00 3F 00 UTF-16LE or little-endian ISO-10646-UCS-2 or other encoding with a 16-bit code unit in little-endian order and ASCII characters encoded as ASCII values (the encoding declaration must be read to determine which)
3C 3F 78 6D UTF-8, ISO 646, ASCII, some part of ISO 8859, Shift-JIS, EUC, or any other 7-bit, 8-bit, or mixed-width encoding which ensures that the characters of ASCII have their normal positions, width, and values; the actual encoding declaration must be read to detect which of these applies, but since all of these encodings use the same bit patterns for the relevant ASCII characters, the encoding declaration itself may be read reliably
4C 6F A7 94 EBCDIC (in some flavor; the full encoding declaration must be read to tell which code page is in use)
Other UTF-8 without an encoding declaration, or else the data stream is mislabeled (lacking a required encoding declaration), corrupt, fragmentary, or enclosed in a wrapper of some kind
Byte Order Markなし

00 00 00 3C UCS-4または、ほかの符号化であって、32ビットのコード単位を持ち、ASCII文字をASCIIコード値として符号化するもので、それぞれ、big-endian(1234)、little-endian(4321)、2つの普通ではないオクテット順(2143と3412)とする。UCS-4とそのほかの32ビットの符号化とのどちらであるかを決定するためには、符号化宣言を読み込まなくてはならない。
3C 00 00 00
00 00 3C 00
00 3C 00 00
00 3C 00 3F UTF-16BEかbig-endianの ISO-10646-UCS-2。または、そのほかの16ビットのコード単位を持つbig-endianの符号化方式であって、ASCII文字をASCIIコード値として符号化するもの(これらのうちどの符号化方式であるかを判定するためには、符号化宣言を読み込まなくてはならない)。
3C 00 3F 00 UTF-16LEかlittle-endianの ISO-10646-UCS-2。または、そのほかの16ビットのコード単位を持つlittle-endianの符号化方式であって、ASCII文字をASCIIコード値として符号化するもの(これらのうちどの符号化方式であるかを判定するためには、符号化宣言を読み込まなくてはならない)。
3C 3F 78 6D UTF-8、ISO 646、ASCII、ISO 8859の各パート、Shift-JIS、EUC、ならびに任意のほかの7ビット、8ビットまたは混在幅の符号化方式であって、ASCII文字を通常の位置、幅および値とすることを保証するもの。これらのどれが使われているかを検出するためには、実際の符号化宣言を読み込まなければならないが、これらすべての符号化方式は、関係するASCII文字に対して同じビットパターンを使用するので、符号化宣言自体は、正確に読み込むことができる。
4C 6F A7 94 EBCDIC(またはその変種。どのコードページを使用するかを知るためには、符号化宣言全体を読み込まれなければならない)。
そのほか 符号化宣言なしのUTF-8か、データストリームに誤ったラベルが付されている(必要な符号化宣言が欠落している)か、損傷しているか、文書の断片であるか、何らかの形式に従って埋め込まれている。

 この表には、詳しい説明が付いているので、その説明文をじっくり読んでいこう。

 まず、上の4種類に付いている説明は、要するに実用上はUCS-4だということなのだが、たまたま同じコードに符号を行うコード体系がほかにもあり得るので、あえて複雑ないい回しになっているのだろう。4種類の順序についてはすでに説明したとおりである。

 次で重要なことは、この4バイト(オクテット)だけではUCS-4と別の符号化方式を区別することはできないが、別の符号化方式が「32ビットのコード単位を持ち、ASCII文字をASCIIコード値として符号化するもの」であるならば、符号化宣言を解析するために必要な条件が確定するのである。つまり、符号化宣言はASCIIコード値だけで記述されるので、符号化宣言を読み込むことができる。

 ちなみに、この例の4バイト(オクテット)は、すべて「<」という1文字を示している。

 次は、00 3C 00 3Fというバイト(オクテット)列の場合である。UTF-16BEは、big-endianのUTF-16BEである。ISO-10646-UCS-2は、(厳密には正しくないが)UTF-16からサロゲートペアのコードを除外したものと考えてよいだろう。ISO-10646-UCS-2のスーパーセットがUTF-16と考えることができ、UTF-16のシステムでISO-10646-UCS-2を処理しても特に問題はないと思うので、両者を区別する必然性は薄いだろう。この後に続く文章の意味するところはUCS-4などと同じである。

 次は、3C 00 3F 00というバイト(オクテット)列の場合である。この意味するところは、little-endianとbig-endianの相違を除き、big-endianの場合と同じである。

 ちなみに、これら例の4バイト(オクテット)は、すべて「<?」という2文字を示している。

 次は、3C 3F 78 6Dというバイト(オクテット)列の場合である。ここの意味は、ASCIIとの多くの互換性を持つ符号化方式である場合ということである。実は、完全か不完全かは別として、多くの符号化方式はさまざまな互換性の要請から、ASCIIと互換性を持たされている。むしろ、互換性がないものの方が珍しいとすらいえる。UCS-2/4、UTF-16、EBCDIC系など、こちらを数える方が楽なほどである。

 ASCIIと完全な互換性がない符号化方式(例えばUS-ASCIIは0x5cはバックスラッシュであるにもかかわらずシフトJISは0x5cが円記号という非互換性がある)であっても、符号化宣言の解析でそれが問題になることはない。

 ちなみに、これら例の4バイト(オクテット)は、すべて「<?xm」という4文字を示している。

 次は、4C 6F A7 94というバイト(オクテット)列の場合である。EBCDICはメインフレームなどで使用される符号化方式であるが、ASCIIとの互換性は存在しない。従って、同じ文字列で書き始められていても、バイト(オクテット)列は同じにならず、識別することができる。

 ちなみに、これら例の4バイト(オクテット)は、すべて「<?xm」という4文字を示している。

 最後は「そのほか」のバイト(オクテット)列の場合である。順当に実装するとすれば、この場合はUTF-8だと認識するのが妥当な解釈だろう。しかし、UTF-8として正当に解釈できない場合は、壊れていると見なすのが妥当だろう。そのほかの解釈として、文書の断片という可能性がある。文書の断片は「<?xml」で始まると決まっているわけではなく、何によって書き始められているか何の予測もできない。そして、XMLプロセッサは文書の断片を解析しなければならない義務をまったく背負っていないし、おそらく何の前提もない状態で解析しようとしてもできないだろう。

 最後の「何らかの形式に従って埋め込まれている」とは、符号化方式の指定がXML文書に埋め込まれているという意味ではなく、XML文書がほかの形式のデータフォーマットの中に埋め込まれていることを意味する。例えば、XML文書の手前に電子メールのヘッダが付加された状態でファイルに保管されているようなケースはあり得るだろう。そのほか、アーカイブファイルや、圧縮されたファイルなど、XML文書でありながら先頭が上記のバイト列のいずれにも該当しないケースがあるだろう。このようなXML文書を解析しなければならない義務をXMLプロセッサは背負っていないが、そのようなXML文書も受け付けるXMLプロセッサを開発することが禁止されているわけでもない。

 まだ途中であるが、分量の都合で今回はここまでである。次回は、この表に対する備考や説明を読むことで、表の理解を深めていこう。また、その後に続く、「G W3C XML Working Group (Non-Normative)」「H W3C XML Core Working Group (Non-Normative」といったワーキングループメンバーのリストに触れた後、最後の「I Production Notes (Non-Normative)」にも触れてみたい。これはたった1段落であるが、規格文書というものが、文書作成技術的な意味でどのように生み出されているかに触れるために、非常に興味深い内容を含んでいる。可能な限り、この内容に深く突っ込んでみたい。そして、これを読み切れば、XML勧告を読むという挑戦が完了することになる。(次回に続く)

3/3

 Index
やさしく読む「XML 1.0勧告」 第37回
文字符号化方式にまつわるジレンマ
  Page 1
・決定的内容モデルと文字符号化方式
・決定的内容モデル
  Page 2
・日本語利用者に関係の深い文字符号化の自動検出
Page 3
・外部の符号化情報がない場合の検出


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


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

注目のテーマ

HTML5+UX 記事ランキング

本日月間