第28回 文字符号化の問題に決着を付ける Page 3

川俣 晶
株式会社ピーデー
2004/12/17

エラーとなる符号化のケース

 次は、符号化に関して誤りと見なすケースについての規定である。

In the absence of information provided by an external transport protocol (e.g. HTTP or MIME), it is a fatal error for an entity including an encoding declaration to be presented to the XML processor in an encoding other than that named in the declaration, or for an entity which begins with neither a Byte Order Mark nor an encoding declaration to use an encoding other than UTF-8. Note that since ASCII is a subset of UTF-8, ordinary ASCII entities do not strictly need an encoding declaration.

外部の伝送プロトコル(すなわちHTTP、MIMEなど)で与えられる情報が存在しない場合、XMLプロセサに渡された実体が、符号化宣言を含むにもかかわらず、宣言で示したもの以外の方式で符号化されているとき、またはマークでも符号化宣言でも始まらない実体が、UTF-8以外の符号化を使用したときは、致命的誤り(fatal error)とする。ASCIIはUTF-8のサブセットなので、通常のASCIIの実体は厳密には符号化宣言を必要としないことに注意。

 冒頭の文章は2つのケースについて書かれている。最初のケースは、実体の外部から符号化に関する情報が与えられていない場合、符号化宣言と実際の符号化が食い違っている場合は誤りとする、ということである。ここで注意すべき点は、誤りになるのはあくまで「実体の外部から符号化に関する情報が与えられていない場合」に限られるということである。実体の外部から情報が与えられて「いる」場合には、食い違いが生じても誤りにはならない。外部の情報が優先されるためである。これは文字符号化スキームを変換してしまうプロキシサーバなどを経由して実体を送る場合に有効な規定である。

 もう1つのケースは、同じく「実体の外部から符号化に関する情報が与えられていない場合」に、マークも符号化宣言も持たない実体が、UTF-8以外の符号化を使うと誤りであると述べている。逆にいえば、UTF-8を使っていれば、マークも符号化宣言も省略できるということである。UTF-8がデフォルトであり標準であるという現在のインターネットの標準の流れに沿った規定といえる。

 次の文章は、UTF-8とASCIIの関係から必然的に導き出されることである。UTF-8はUS-ASCIIの完全なスーパーセットになるように作られている。つまり、すべてのUS-ASCIIの文書は、(本来US-ASCIIの一部ではない8bit目をオンにするような使い方をしていない限り)UTF-8として処理しても正常に処理されるということである。このような構造は、アメリカ人にだけ従来の符号化からUTF-8に移行する手間を極端に減らし、他国の利用者から見て不公平のようにも思えるが、UTF-8の発明によってやっとアメリカ人も重い腰を上げてUnicodeやISO/IEC 10646への移行が始まったと思えば、それほど悪いものでもない。また、US-ASCIIを前提とする多くのシステム、プロトコルのUnicodeやISO/IEC 10646への対応が容易になったという効能もある。

 次は、テキスト宣言の出現位置についての規定である。

It is a fatal error for a TextDecl to occur other than at the beginning of an external entity.

TextDeclが外部実体の先頭以外の場所に出現することは、致命的な誤り(fatal error)とする。

 ここのTextDeclとは、生成規則[77] TextDeclのテキスト宣言に該当する。では、ここではどうしてテキスト宣言と書かずにTextDeclと書いたのだろうか。おそらく、テキスト宣言という特定の機能が意図された記述を禁止する規定ではなく、TextDeclという生成規則にマッチする文字列の出現を禁止する、という意図の規定だからであろう。そのような文字列を外部実体の先頭以外に書けば、それは致命的な誤りとなる。

 次は、さらに符号化の誤りに関する規定である。

It is a fatal error when an XML processor encounters an entity with an encoding that it is unable to process. It is a fatal error if an XML entity is determined (via default, encoding declaration, or higher-level protocol) to be in a certain encoding but contains byte sequences that are not legal in that encoding. Specifically, it is a fatal error if an entity encoded in UTF-8 contains any irregular code unit sequences, as defined in Unicode 3.1 [Unicode3]. Unless an encoding is determined by a higher-level protocol, it is also a fatal error if an XML entity contains no encoding declaration and its content is not legal UTF-8 or UTF-16.

処理できない符号化を使用した実体をXMLプロセサが発見したときは、致命的な誤り(fatal error)とする。XML実体が(デフォルトで、符号化宣言によって、またはより高次のプロトコルによって)ある符号化であると確定されるが、その符号化としては正しくないオクテット列を含む場合は、致命的な誤りとする。特に、UTF-8で符号化された実体が、不正であるとUnicode 3.1で定義されたコードユニット列を含むことは致命的な誤りとする。上位のプロトコルによって符号化が決まらない場合、 符号化宣言を含まないXML 実体が、正しいUTF-8またはUTF-16の内容を持たないときも、致命的な誤りとする。

 冒頭の文章で述べているのは当然のことであるが、処理できない符号化を使用した実体に出合った場合、それは丸ごとすべて処理できないことになるので、それ以上意味のある処理を継続することはできない。

 次の文章にある規定の意義は、多くの電子メールシステムが、ISO-2022-JPに含まれない機種依存文字を示すコードを平然と受け渡している状況を見れば明白だろう。それが本来は使用できない機種依存文字の利用を普及させ、トラブルのもとになっている。つまり、指定された符号化で規定されていないコード、オクテット列を右から左へ平然と通せば、それは後々大きな問題を引き起こすリスクとなる。安全のためには、それらを明確にシャットアウトする価値がある。

 次に意外とありがちなケースを述べている。UTF-16のサロゲートペアをUTF-8に変換する場合の処理の誤りである。サロゲートペアは2つの16bitコードの組み合わせで表現されるが、これをUTF-8に符号化する方法は2つある。1つは、サロゲートペアの前半と後半を別個の文字と見なす方法で、これを行うと、16bitコードをUTF-8に置き換える作業が「2回」発生する。しかし、これは誤りである。正しくは、その文字のコード(U+1XXXXのような番号)からUTF-8に置き換える作業を「1回だけ」行う。しかし、誤った実装であっても、UTF-16→UTF-8→UTF-16という変換を行うと元のコードに戻るので、間違いに気付きにくい。しかし、この規定により、誤った変換の結果のコードは致命的な誤りとなり、そこで気付くことができる。

 最後の文章にある上位のプロトコルとは、これまで読んできた文章に出てきた「外部」と考えてもよいだろう。つまり、電子メールやHTTPのヘッダなどで符号化が指定されておらず、符号化宣言も含んでいない実体は、UTF-8かUTF-16のどちらか一方でなければならない、ということである。この2つは、マークによって相互に区別可能なので、どちらを使っているかの情報は(マーク以外に)示される必要はない。そして、UTF-8とUTF-16のどちらでもない場合は致命的なエラーとなる。何のヒントもなく、符号化を正しく判定することはほとんど不可能であるから、当然の規定といえる。世の中には多少の自動判定が実現されている事例があるが、XMLが扱う対象符号化の種類の多さを考えれば、それらの間の自動判定はほとんど不可能といってよいだろう。

符号化宣言を含むテキスト宣言の例

 以下は符号化宣言を含むテキスト宣言の例である。

Examples of text declarations containing encoding declarations:

<?xml encoding='UTF-8'?>
<?xml encoding='EUC-JP'?>

 以上で「4.3.3 Character Encoding in Entities(4.3.3 実体における文字符号化)」をすべて読み切った。符号化は非常に悩ましい問題に満ちている。その詳細は、XML日本語プロファイルを読んでもらいたいが、Unicode変換テーブルの不統一問題は致命的な非互換性を発生させている。これを回避するには、変換テーブルを使わない、つまり最初からUnicodeであるUTF-16あるいはUTF-8を使っていくしかない、という状況である。しかも、それを行ってすら、完全な解決にはならない。例えば、UTF-8でXML文書を書いてバックスラッシュ記号を書き込んでWindows付属のMS明朝などのフォントで見ると、バックスラッシュ記号は見事円記号に化けて見えるのである(これはフォントが規格に準拠していないために起こる現象であるが、フォントを直すと、今度はWindowsの操作に致命的な非互換性が発生してしまうのである)。

 さて、次回は「4.4 XML Processor Treatment of Entities and References(4.4 XMLプロセッサによる実体および参照の扱い)」を読んでいこう。XMLには多くの種類の実体があり、さまざまな場所から参照できる。しかし、すべての場所からすべての種類の実体を参照できるわけではない。そのあたりの詳細を読んでいくことにしよう。(次回に続く)

3/3

 Index
やさしく読む「XML 1.0勧告」 第28回
文字符号化の問題に決着を付ける
  Page 1
・実体における文字符号化の問題解決を探る
・サポートすべき符号化の規定
  Page 2
・符号化宣言のEBNFによる生成規則
・符号化宣言に記述する文字符号化スキーム名
Page 3
・エラーとなる符号化のケース
・符号化宣言を含むテキスト宣言の例


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


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

注目のテーマ

HTML5+UX 記事ランキング

本日月間