UTF-8でのXMLドキュメントのエンコード

(ヒント:サイズは関係ない)

Unicodeは、現存する他のすべての重要なコンピュータ化文字セットのスーパーセットです。UTF-8は、Unicode文字セットの適切なバイナリー・エンコードです。この記事は、すべてのXMLドキュメントがもっぱらUTF-8で生成されるべきであると主張しています。その結果、ドキュメントの世界がより堅牢で、より相互運用性の高いものになります。

Elliotte Rusty Harold (elharo@metalab.unc.edu), Adjunct Professor, Polytechnic University

Photo of Elliot Rusty HaroldElliotte Rusty Haroldはニューオーリンズ出身であり、時たま、おいしいgumbo(オクラ入りのスープ)を食べに帰っています。ただし現在はニューヨークのブルックリン近郊のProspect Heightsに、妻のBethと猫のCharm(charmed quarkからとりました)とMarjorie(義理の母の名前からとりました)と一緒に住んでいます。彼はPolytechnic Universityのコンピューター・サイエンスの非常勤教授として、Java技術とオブジェクト指向プログラミングを教えています。彼のCafe au Lait Webサイトは、インターネット上で最も人気のある独立系Javaサイトの一つです。また、そこから派生したCafe con Lecheは、最も人気のあるXMLサイトの一つです。彼の著作にはEffective XMLProcessing XML with JavaJava Network Programming 、それにThe XML 1.1 Bible があります。現在はXML処理用のXOM APIやJaxen XPathエンジン、Jesterテスト・カバレッジ・ツールなどに取り組んでいます。



2005年 8月 30日

Googleのサイトマップ・サービスは、最近、すべてのサイトマップがもっぱらUnicodeのUTF-8エンコードで発行されなければならないと要求して、XMLコミュニティーにちょっとした動揺を引き起こしました。Googleは、UTF-16など、代替のUnicodeエンコードさえ許さず、ましてISO-8859-1などの非Unicodeエンコードは言うまでもありません。技術的には、これはGoogleが非準拠のXMLパーサーを使用していることを意味します。XML勧告では、「すべてのXMLプロセッサーはUnicode 3.1のUTF-8およびUTF-16エンコードを受け入れなければならない」と明確に要求しているからです。しかし、これは本当にそれほど大きな問題なのでしょうか。

誰もがUTF-8を使用できる

普遍性は、UTF-8を選ぶ最初にして最大の理由です。UTF-8は、現在、地球上で使用されているほとんどすべてのスクリプトをうまく扱うことができます。いくらかのギャップは残っていますが、ますます目立たなくなり、埋められつつあります。カバーされていないスクリプトは、一般に、他の文字セットでも実装されていません。実装されているとしても、XMLでは使用できません。せいぜいが、Latin-1のような1バイト文字セットに接木されたフォント・ハックによってカバーされている程度です。これらの少数派スクリプトの真のサポートは、Unicodeが最初になるでしょうし、おそらくUnicodeだけでしょう。

しかし、これはUnicodeの使用に関する主張の1つに過ぎません。なぜUTF-16や他のUnicodeエンコードではなく、UTF-8を選ぶのでしょうか。最も単純な理由の1つは、幅広いツール・サポートです。JEdit、BBEdit、Eclipse、emacs、そしてメモ帳さえ、XMLで使用される重要なエディターのほとんどすべてが、UTF-8を扱えます。Unicodeのほかのエンコードは、XMLツールにしろ、XML以外のツールにしろ、それほど広くサポートされていません。

BBEditやEclipseのように、UTF-8がデフォルトの文字セットでない場合もあります。そろそろデフォルトを変えるべき時期です。すべてのツールがデフォルトのエンコードとしてUTF-8を標準で選択すべきです。そうならない限り、国、プラットフォーム、および言葉の境界を越えて転送されるときに相互運用性のないファイルが陥る苦境と格闘しなければなりません。しかし、すべてのプログラムがUTF-8にデフォルト設定されるまでは、自分で簡単にデフォルトを変更できます。たとえば、Eclipseでは、図1に示されている[General]-[Editors]Preferencesパネルで、すべてのファイルをUTF-8にするように指定することができます。EclipseのデフォルトはMacRomanです。しかし、その場合、Microsoft® Windows®を使用しているプログラマーや欧米以外のコンピューターにファイルを転送すると、コンパイルできません。

図1.Eclipseでのデフォルトの文字セットの変更
図1.Eclipseでのデフォルトの文字セットの変更

もちろん、UTF-8が機能するためには、ファイルの交換相手である開発者もUTF-8を使用していなければなりませんが、これが問題になることはありません。MacRomanと違って、UTF-8は少数のスクリプトと1つの少数派プラットフォームに限定されません。UTF-8は、誰でも使えます。MacRoman、Latin-1、SJIS、その他、国別のレガシー文字セットでは、そうはいきません。

UTF-8は、マルチバイト・データを受け取ることを予期していないツールでも使えます。UTF-16など、他のUnicodeフォーマットは、多数のゼロ・バイトを含む傾向があります。少なからぬ数のツールが、これらのバイトをEOF(ファイル終了)やその他の特殊な区切り文字と解釈して、予想外の、そして一般に望ましくない結果をもたらします。たとえば、UTF-16データがC文字列に単純にロードされた場合、文字列は最初のASCII文字の2番目のバイトで切り詰められることがあります。UTF-8ファイルは、実際にヌルを意味するヌルしか含みません。もちろん、このような単純なツールではXMLドキュメントを処理しないことにするという方法もあります。しかし、レガシー・システムでは、ファイルが奇妙な場所で終わることがしばしばあり、古いボトルに新しいワインを入れた結果を予想できる人は誰もいません。UTF-8は、UTF-16やその他のUnicodeエンコードに比べると、UnicodeとXMLを認識しないシステムでも問題を起こす可能性が少ないのです。


仕様ではどうなっているか

XMLは、初めてUTF-8を全面的に支持した主要標準ですが、これはトレンドの始まりに過ぎませんでした。ますます多くの標準化団体がUTF-8を推奨するようになっています。たとえば、非ASCII文字を含むURLは、長い間、Webを苦しめてきた問題です。非ASCII文字を含んでいるURLは、PC上では問題がなくても、Macに読み込むと問題が発生したり、その逆だったりします。この問題は、最近、W3C(World Wide Web Consortium)とIETF(Internet Engineering Task Force)が、すべてのURLをUTF-8でエンコードすることで合意し、解消されました。

W3CとIETFはいずれも、最近、UTF-8を最初に、最後に、またときどきだけ選ぶことに関して、より強い姿勢を示すようになってきました。「World Wide Webの文字モデル 1.0:基本」は、次のように述べています。「一意な文字エンコードが必要なときは、文字エンコードはUTF-8、UTF-16、またはUTF-32でなければならない。US-ASCIIはUTF-8と上位互換があり(US-ASCII文字列はUTF-8文字列でもある[RFC 3629]参照)、したがって、UTF-8はUS-ASCIIとの互換性が必要な場合に適している。」実際には、US-ASCIIとの互換性は非常に実用度が高く、ほとんど要件となっています。W3Cは賢明にも次のように説明しています。「APIなど、他の状況では、UTF-16またはUTF-32の方が適しているかもしれない。これらの1つを選ぶ理由としては、内部処理の効率性と他のプロセスとの相互運用性が考えられる。」

私は、内部処理の効率性に関する主張は正しいと思います。たとえば、JavaTM言語の文字列の内部処理はUTF-16に基づき、文字列の索引付けが非常に高速になります。しかし、Javaコードは、これらの内部表現を、データを交換する相手のプログラムに公開することはありません。その代わり、外部データ交換にはjava.io.Writerが使用され、文字セットは明示的に指定されます。このような選択をするときには、UTF-8が特に望ましいでしょう。

IETFは、さらに明確です。「IETF文字集合方針」[RFC 2277]の規定には、あいまいな点はまったくありません。

  • プロトコルは、あらゆるテキストについて、UTF-8文字集合を使用できなければならない。UTF-8文字集合は、[10646]付属R(修正2で発行)で定義されているように、UTF-8文字エンコード方式と組み合わされたISO 10646符号化文字集合で構成される。
  • さらに、プロトコルは、UTF-16など、他の文字集合またはISO 10646の他の文字エンコード方式の使用方法を指定してもよいが、UTF-8を使用する能力の欠如は、この方針の違反となる。このような違反があった場合は、標準化過程に入る前、または標準化過程を進める前に、プロトコル仕様書での明確かつ確固たる正当化による特例的認可手続き([BCP9]第9章)が必要である。
  • 既存のデータ・ストアからデータを移動する既存のプロトコルの場合、他の文字集合のサポート、またはUTF-8以外のデフォルトを使用することさえも必須事項かもしれない。これは容認できるが、UTF-8のサポートが可能でなければならない。

中国語、日本語、および韓国語

UTF-8は圧縮形式だというのは、よくある誤解です。そうではありません。ASCII範囲の文字は、UTF-8では、Unicodeの他のエンコード、特にUTF-16の半分のスペースしか占めません。しかし、一部の文字は、UTF-8でエンコードするには最大50%増しのスペースを必要とします。特に中国語、日本語、および韓国語(CJK)の表意文字がそうです。

しかし、UTF-8でCJKのXMLをエンコードするときでも、UTF-16と比較した実際のサイズ増は、おそらく、それほど大きくありません。たとえば、中国語のXMLドキュメントには、<、>、&、=、"、'、スペースなど、多くのASCII文字が含まれます。これらはすべて、UTF-16よりもUTF-8での方が小さくなります。正確な縮小率または膨張率はドキュメントごとに違いますが、いずれにしても、差異はそれほど決定的ではありません。

最後に、中国語や日本語のような表意文字は、LatinやCyrillicなどのアルファベットに比べて、文字数が少なくなる傾向がある点に注目する必要があります。これらの文字の大多数を完全に表現するには、1文字あたり3バイト以上が必要です。このことは、同じ単語や文を英語やロシア語などの言語より少ない文字で表現できることを意味します。たとえば、treeを表す漢字は「木」です。(形が木に似ています。)この漢字はUTF-8では3バイトを占めますが、英単語のtreeは4文字であり、4バイトを占めます。groveを表す漢字は「林」です(2本の木が並んでいます)。この漢字もUTF-8では3バイトを占めますが、英単語のgroveは5文字であり、5バイトを占めます。「森」という漢字(3本の木)も3バイトです。しかし、これに相当する英単語forestは6バイトです。

本当に圧縮したい場合は、zipまたはgzipでXMLを圧縮してください。元のサイズの差に関係なく、圧縮されたUTF-8は圧縮されたUTF-16とほぼ同じサイズになります。圧縮前に大きかった方は、圧縮アルゴリズムによって削除される冗長度が高かったということです。


堅牢性

意外な利点として、設計上、UTF-8はそれ以前またはそれ以降に設計されたいかなる他のテキスト・エンコードより堅牢性が高く、解釈しやすい形式です。まず、UTF-16と違って、UTF-8にはエンディアン問題がありません。ビッグ・エンディアンUTF-8とリトル・エンディアンUTF-8は同じです。UTF-8は16ビット・ワードではなく8ビット・バイトとして定義されているからです。UTF-8には、バイト・オーダー・マークやその他の経験則によって解決しなければならないようなバイト・オーダーのあいまいさがありません。

さらに重要なUTF-8の特性は、ステートレスであることです。UTF-8ストリームまたはシーケンスの各バイトには、あいまいさがありません。UTF-8では、常に今いる場所がわかります。すなわち、1バイトが与えられたとき、それが1バイト文字なのか、2バイト文字の最初のバイトなのか、2バイト文字の2番目のバイトなのか、それとも3バイトまたは4バイト文字の2番目、3番目、または4番目のバイトなのかがすぐにわかります。(わからない可能性がまったくないわけではありませんが、想像はつきます。)UTF-16では、バイト"0x41"が英字の"A"かどうか、常にわかるわけではありません。そうかもしれないし、そうでないかもしれません。ストリーム内のどこにいるのかを知るには、ステートの経過を十分に知らなければなりません。1バイトが失われた場合、その時点から先のすべてのデータが破損します。UTF-8では、失われたバイトや壊れたバイトがあっても容易に見分けることができ、残りのデータが破損することもありません。

UTF-8は、あらゆる目的に最適というわけではありません。ドキュメント内の特定の索引へのランダム・アクセスを必要とするアプリケーションの場合は、UCS2やUTF-32などの固定幅エンコードを使用した方が動作が迅速かもしれません。(サロゲート・ペアを考慮に入れると、UTF-16は可変幅の文字エンコードです。)しかし、XML処理は、そのようなアプリケーションではありません。XML仕様では、パーサーはXMLドキュメントの最初のバイトから解析を開始して、終わりまで解析を続けることを具体的に要求していて、既存のすべてのパーサーがこのように振る舞っています。ランダム・アクセスが高速でも、XML処理には何の役にも立ちません。データベースなどのシステムでは、これが別のエンコードを使用する格好の理由となるかもしれませんが、XMLには該当しません。


まとめ

国際化が進むにつれて、言葉や政治の境界がますますあいまいになり、ロケールに依存する文字セットは現実的ではなくなっています。Unicodeは、地球上の多くのロケールにまたがって相互運用可能な唯一の文字セットです。UTF-8は、Unicodeの正しいエンコードです。

  • レガシーASCIIシステムとの互換性も高く、広範なツール・サポートを提供します。
  • 処理が簡単で効率的です。
  • 破損に強い性質を持っています。
  • プラットフォーム中立です。

文字セットとエンコードに関する議論はやめる時期です。UTF-8を選んで、議論に終止符を打ちましょう。

参考文献

コメント

developerWorks: サイン・イン

必須フィールドは(*)で示されます。


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


お客様が developerWorks に初めてサインインすると、お客様のプロフィールが作成されます。会社名を非表示とする選択を行わない限り、プロフィール内の情報(名前、国/地域や会社名)は公開され、投稿するコンテンツと一緒に表示されますが、いつでもこれらの情報を更新できます。

送信されたすべての情報は安全です。

ディスプレイ・ネームを選択してください



developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

必須フィールドは(*)で示されます。

3文字から31文字の範囲で指定し

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


送信されたすべての情報は安全です。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=XML
ArticleID=242737
ArticleTitle=UTF-8でのXMLドキュメントのエンコード
publish-date=08302005