レベル: 中級 Uche Ogbuji (uche@ogbuji.net), Consultant, Fourthought, Inc.
2004年 4月 09日 バイナリXMLは、多くの議論を引き起こしました。バイナリXMLを推進する根拠の一つは、特にWebサービスで使用するために、より冗長性の少ない転送フォーマットが必要であるという点です。その答えの一つとして既に手元にあるのは、データ圧縮です。このヒントでは、WebサービスでXMLを伝送するために、どのように圧縮を利用するのかを説明します。
バイナリXMLという考え方は、以前からXMLの議論の合間で、いつもちょっとした話題になっていました。XMLはテキスト型であるという宿命や、国際化に対応し易くするための多くの規則によって、非常に冗長になっています。同じものをバイナリ構文で表現すれば、はるかにコンパクトなものになります。私は初期(2000年)の記事「XML The future of EDI?」(参考文献参照)で、ANSI EDI X12形式の注文書トランザクション(バイナリ)の一部をXMLに変換する方法を説明しました。そこでの変換結果では、XMLの大きさが元のEDIメッセージの8倍以上になっています(他の幾つかの試験的なXML/EDI変換では、3倍程度のものもあります)。この冗長性は、XMLの保存という面ではやや気になりますが、最近では少なくとも保存にかかるコストは安価になっています。普通は伝送能力の方が限られており、バイナリXMLを要求する声が最も大きいのは、メッセージ転送形式としてXMLを使う人達(一部のWebサービスのユーザを含めて)の間からでした。
XML圧縮を実現するための手法の一つは、最初からバイナリ・フォーマット用に設計された形式を使用することです。その最有力候補が、XML以前に登場したデータ伝送標準であるISO/ITU ASN.1です。ASN.1は、XMLフォーマットをASN.1 Packed Encoding Rulesのような特別な形式に、再編成することを可能にするXML関連機能の幾つかを使って更新されており、非常にコンパクトなバイナリ・エンコードを定義しています。OASIS UBLは、XMLデータの圧縮に関してASN.1の手法をとったXMLの動向の一例です。
SOAPエンコーディングのための圧縮
WebサービスでXMLを伝送しようとする場合、ペイロードが冗長すぎると思えるかも知れません。その場合には、XMLコンテンツに対する多くのテキスト圧縮の選択肢のうちのどれかを使うことができます。リスト1は、以前に書いた記事の中で示したXML/EDIの例です。
リスト1. Webサービスでの交換用XML文書の例
<?xml version="1.0" encoding="UTF-8"?>
<PurchaseOrder Version="4010">
<PurchaseOrderHeader>
<TransactionSetHeader X12.ID="850">
<TransactionSetIDCode code="850"/>
<TransactionSetControlNumber>12345</TransactionSetControlNumber>
</TransactionSetHeader>
<BeginningSegment>
<PurposeTypeCode Code="00 Original"/>
<OrderTypeCode Code="SA Stand-alone Order"/>
<PurchaseOrderNumber>RET8999</PurchaseOrderNumber>
<PurchaseOrderDate>19981201</PurchaseOrderDate>
</BeginningSegment>
<AdminCommunicationsContact>
<ContactFunctionCode Code="OC Order Contact"/>
<ContactName>Obi Anozie</ContactName>
</AdminCommunicationsContact>
</PurchaseOrderHeader>
<PurchaseOrderDetail>
<Name1InformationLOOP>
<Name>
<EntityIdentifierCode Code="BY Buying Party"/>
<EntityName>Internet Retailer Inc.</EntityName>
<IdentificationCodeQualifier Code="91 Assigned by Seller"/>
<IdentificationCode>RET8999</IdentificationCode>
</Name>
<Name>
<EntityIdentifierCode Code="ST Ship To"/>
<EntityName>Internet Retailer Inc.</EntityName>
</Name>
<AddressInformation>123 Via Way</AddressInformation>
<GeographicLocation>
<CityName>Milwaukee</CityName>
<StateProvinceCode>WI</StateProvinceCode>
<PostalCode>53202</PostalCode>
</GeographicLocation>
</Name1InformationLOOP>
<BaselineItemData>
<QuantityOrdered>100</QuantityOrdered>
<Unit Code="EA Each"/>
<UnitPrice>1.23</UnitPrice>
<PriceBasis Code="WE Wholesale Price per Each"/>
<ProductIDQualifier Code="MG Manufacturer Part Number"/>
<ProductID Description="Fuzzy Dice">CO633</ProductID>
</BaselineItemData>
</PurchaseOrderDetail>
</PurchaseOrder>
|
元のEDIのサンプルは、サイズが200バイトで、XML版では1721バイトになっています。
有名なPK-ZIPルーチンは、このXMLファイルを832バイトに圧縮します。
GNU gzipルーチンは、このファイルを707バイトに圧縮します。
オープン・ソースのルーチンbzip2は、748バイトに圧縮します。
これらのどれも、専用のEDIフォーマットほどにはコンパクトではありませんが、それは当然と言えます。bzip2は多くのファイルに対してgzipよりも(遅いとは言え)圧縮率が高いことで有名ですが、ここでは私が通常見かける結果と変わらず、XMLはbzip2よりもgzipで圧縮した方が小さくなるようです。
最近では大部分のプラットフォームや言語が、少なくともPK-ZIPやGNU gzip圧縮用のライブラリを備えており、Webサービスを呼び出す前に、プログラムで圧縮を行うことができるようになっています。
皆さんが自分の事例で正規化(canonicalization:C14N)を適用する場合には、圧縮が改善するのか悪化するのかをよく調べてください。C14Nは、意味を変えない範囲で許されるXML構文の変更を明確にしたもの(正規化形式と呼ばれます)で、XML文書の物理的な表現を作成する際の標準的な方法です。大まかに言って、XMLが手で編集されたものであって属性の順序や空白の使い方に大きなバラツキがあり得る場合、大きな文書であれば、C14Nで圧縮のパフォーマンスを改善できるかも知れません。ところが、XMLが機械で生成されたものである場合や、空要素を大量に使っている場合には、C14Nを使うと悪影響があるかも知れません。私の例は、後者の場合に近いと言えます。私はPyXMLプロジェクトのC14Nモジュールを使って正規化を行ないました。Pythonコードは下記の通りです。
>>> from xml.dom import minidom
>>> from xml.dom.ext import c14n
>>> doc = minidom.parse('listing1.xml')
>>> c14n.Canonicalize(doc)
>>> f = open('listing1-canonical.xml', 'w')
>>> c14n.Canonicalize(doc, output=f)
>>> f.close()
|
できあがったファイルlisting1-canonical.xmlは、1867バイトであり、gzipで圧縮した後は714バイトです。最初のプレーン・テキスト版(listing1.xml)よりも146バイト大きく、gzipの結果も7バイト大きくなっています。こうなってしまう主な理由は、C14Nを使った後は、最も冗長な形式で空要素が表現されるためです。例えば次のような行は・・・
以下のようになります。
<Unit Code="EA Each"></Unit>
|
gzipなどで圧縮したXMLをSOAPにバンドルするには、2つの選択肢があります。
- 何らかの添付機能を使う
- メッセージの本体に含めるためにBase64のようなエンコーディングを使う
Base64は、通常のテキスト文字のみを使用してバイナリ文書を表現します。こうしたライブラリは、どのようなプラットフォーム上でも利用可能なので、それを使って処理できるはずです。W3CのXML Schemaには、Base64でエンコードされたデータに対する型まで存在しており、Webサービスを適切に設定しさえすれば、Base64のエンコード/デコードを皆さんの使っているツールで自動化できるかも知れません。しかし残念ながらBase64エンコーディングは、圧縮の効果を一部打ち消してしまいます。Base64エンコーディングでは、4:3の割合で元のファイルよりも大きくなります。Base64でエンコードした後に、リスト1をgzipで圧縮した結果は957バイトになります。
まとめ
一般的に言って、XMLファイルにgzipを適用し、SOAPにインライン化して伝送するために、圧縮した結果をBase64でエンコードすると、その結果は多くの場合、元のサイズの半分になります。これだけでも、皆さんが必要とするXML Webサービスでのスペースの節約には十分かも知れません。これで十分でなければ、ASN.1をよく検討してみてください。
参考文献
著者について  | 
|  | Uche Ogbuji氏は、Fourthought, Inc. のコンサルタント兼共同設立者です。この会社は、企業のナレッジ・マネジメントのためのXMLソリューションを専門とするソフトウェア・ベンダー兼コンサルタント会社です。Fourthoughtでは、XML、RDF、およびナレッジ・マネジメント・アプリケーション用のオープン・ソース・プラットフォームである4Suiteを開発しています。Ogbuji氏は、ナイジェリア出身のコンピューター・エンジニア兼ライターで、現在は、米国コロラド州ボールダーに住み、そこで働いています。Ogbuji氏の連絡先はuche.ogbuji@fourthought.com です。 |
記事の評価
|