目次 | |
---|---|
この報告は J2ME 環境、特に携帯電話の Java アプリケーション実行環境において、XML パーサを使用する際の注意点や問題点について調査したものである。ここで使う XML パーサは通常のバイナリ化されていない XML データを扱うものとする。また、読み込んだ XML データの処理や XML データの生成・出力などについては扱わない。
J2ME (Java2 platform, Micro Edition) は組み込み機器、PDA、携帯電話などのような環境に特化した Java 環境の仕様である。日本では携帯電話キャリア各社が J2ME 環境を内蔵した端末を採用したことで、特に携帯電話向けアプリケーションの主要なプラットフォームとして注目されている。以下、各社の携帯電話の J2ME 環境の仕様や制限などについて、XML パーサを動作させる際に注意が必要な点を見ていく。
J2ME と言っても API の互換性や実行環境の制限などの点で各社異なるのが実情である(参照: [iapp], [japp], [ezplus])。その概要を表1にまとめた。これらのうち API の違いについては XML パーサに直接関係しない。どれも CLDC (Connected, Limited Device Configuration) に準拠しており、XML パーサの機能は CLDC の API だけで実装できる。重要なのは、アプリケーション(JARファイル)のサイズとHTTP通信による一回の転送量の制限である。
サービス名 | キャリア | API | JARサイズ上限 | HTTP通信上限 | 接続先制限 | XML受信に使用可能な メディアタイプ |
|
---|---|---|---|---|---|---|---|
下り | 上り | ||||||
iアプリ(503i) | NTTドコモ | CLDC 1.0 / DoJa 1.0 | 10KB | 10KB | 5KB | ダウンロード先と同一サイト | 制限なし |
iアプリ(504i) | NTTドコモ | CLDC 1.0 / DoJa 2.0 | 30KB | 10KB | 5KB | ダウンロード先と同一サイト | 制限なし |
Javaアプリ | J-Phone | CLDC 1.0 / MIDP 1.0 / JSCL | 30KB/80KB*1 | 80KB*2 | 12KB | 無制限(認可が必要*3) | application/java-archive |
ezplus | KDDI | CLDC 1.0 / MIDP 1.0 / KDDI Profile | 50KB | 9000byte | 9000byte | 3箇所まで設定可能 | application/octet-stream |
*1 80KB はパケット通信対応端末の場合。圧縮したJARファイル(50KBまで)を RecordStore に格納し、そこから展開して読み込むことも可能。この機能を使うと事実上 100〜200KB (圧縮率による)のデータを扱える。
*2 メディアタイプを application/java-archive に設定時。画像・音曲などは12KB。
*3 逆に認可なしでは通信機能は一切利用できない。
アプリケーションが XML を利用する場合最低必要となるのが XML パーサだが、JAR ファイルが数10KB程度に制限される携帯電話の環境では使用できるパーサは限られてくる。
また、携帯電話の環境では HTTP 通信の転送量は 10KB 程度にまで制限されている。もっと制限が緩い場合でも現状では通信速度と課金を考慮してそのぐらいのサイズのデータを主に扱うことになるであろう。一般の XML パーサはもっと大きなサイズのデータでテストされているため、一般に高性能と言われているパーサが有利になるとは限らない。
メディアタイプの制限については注意が必要である。メディアタイプの制限はキャリアのゲートウェイが HTML や画像など特定のメディアタイプのコンテンツしか通さないことから生じる制限である。この制限を避けるためには、サーバー側でコンテンツに本来のメディアタイプ(SVG なら image/svg+xml など)ではないメディアタイプ(例えば application/java-archive)を設定するという、一種の偽装を行う必要がある。携帯電話側のアプリケーションでは HTTP レスポンスのメディアタイプを意識することはほとんどないので問題ないが、同じサーバーが一般の PC にも同じデータを配信している場合には、PC 側のブラウザでデータが表示できなくなる(ダウンロードになってしまう)という問題が発生しうる。
また接続先の制限についても知っておきたい。XML データに DTD や外部実体、XML Schema 文書などへの参照がある場合、接続先制限によって読み込めなくなることがある。現在のところ J2ME で使えるパーサでそれらの外部リソースへの参照を行えるものはほとんどないので実際には問題にならないかもしれないが、将来に向けて留意すべき点ではある。
Java で動く XML パーサは数多いが、携帯電話の J2ME 環境で動くものは少ない。J2ME のAPIの制限からビルドできない、コードサイズが大きすぎる、メモリ使用量が大きい、などの問題で動作しない場合が多い。
そのような問題がないか、比較的簡単な作業でクリアできるものを表2に挙げた。コードサイズについてはパーサが動作する最小の構成で JAR ファイルのサイズが 20KB 程度以下になるものを選んだ。ビルドについては主観的ではあるが、ビルド時のエラーが 100 個以上出るものについてはその内容を検討し修正困難と判断したものを除外した。エラーが 100 個以内のものについては動作可能な状態になるまでソースコードを修正してテストした。
とりあえず動作はしても、実際に性能的・機能的な点で実用に耐えるかどうかという問題はあるが、この点については次章以降で検討する。また、ビルド時に必要な修正作業については「付録B.パーサの修正方法」を参照されたい。
なお、ここに挙げたものはいずれもソースコードを含め無料で入手できる。ただし再配布についてはライセンス上制限される場合がある。Min は独自のライセンス、それ以外はオープンソースライセンスであるが、BSD スタイルのライセンスでも内容が微妙に異なるものがある。詳しくは各パーサの付属文書等を参照されたい。
パーサ名 | バージョン | API | ライセンス | 入手先 |
---|---|---|---|---|
kXML2 | 2.1.3 | Pull + 独自tree | CPL | http://www.kxml.org/ |
MXP1 | 1.1.1c | Pull | BSDスタイル | http://www.extreme.indiana.edu/xgws/xsoap/xpp/mxp1/ |
MinML1 | 1.7 | SAX1 | BSDスタイル | http://www.wilson.co.uk/xml/minml.htm |
MinML2 | 0.3 | SAX2 | BSDスタイル | http://www.wilson.co.uk/xml/minml2.htm |
TinyXML | 0.7 | 独自(event + tree) | GPL | http://www.gibaradunn.srac.org/tiny/ |
NanoXML/Lite | 2.2.1 | 独自(tree) | zlib/libpng | http://web.wanadoo.be/cyberelf/nanoxml/index.html |
Min | 1.05A | SAX1 | 独自 | http://www.docuverse.com/min/ |
API については次章で説明する。API のうちパーサ独自のものについては「各種パーサの特徴」のパーサ毎の説明を参照されたい。
XML パーサがパースした内容をアプリケーションに渡す方法(API)はパーサによって異なる。パーサの API は大別すると以下の三つがある。
ツリー構築型 API は、パースした内容をツリー構造をとったオブジェクトの集合の形でアプリケーションに渡す方式の API である。代表的なものとして DOM が挙げられる。データの扱いやすさから好まれる方式だが、XML データを丸ごとメモリに読み込むため、メモリ使用量に制限のある J2ME 環境での使用には向かないと考えられる。
イベント駆動型 API はパーサがタグ等を検出する度にアプリケーションが実装したイベントハンドラに通知する方式の API である。代表的なものとして SAX が挙げられる。必要なイベントだけを処理しそれ以外を無視でき、処理する場合も処理済のデータをすぐにその場で捨てられるため、メモリ使用量が低く抑えられる。そのため軽量パーサの API に好んで使用されているが、データの扱い方が難しい、イベントハンドラの形で書くとアプリケーションコードがわかりにくくなる、などの理由で敬遠されることも多い。
最後の Pull 型 API はアプリケーション側がパースの進行を制御しながらパースしたデータを引き出す方式の API である。代表的なものとして XML Pull API が挙げられる。イベント駆動型 API と同様メモリ使用量が低く抑えられる一方で、わかりやすいアプリケーションコードが書ける。イベント駆動型 API と比較して、ハンドラインターフェースやその実装(無視するイベントに対しても空の実装が必要になる)、パーサ側のハンドラ呼び出しの分のコードが節約されるのでコードサイズをより小さくできる。このため、現在のところ軽量パーサに最も適した API と考えられている。
具体的な API の特徴については表3にまとめた。
API名 | 方式 | 名前空間 |
---|---|---|
DOM level 1 (DOM1) | ツリー構築型 | × |
DOM level 2 (DOM2) | ツリー構築型 | ○ |
SAX version 1 (SAX1) | イベント駆動型 | × |
SAX version 2 (SAX2) | イベント駆動型 | ○ |
XML Pull API (Pull) | Pull 型 | ○* |
* 実際に機能するかどうかは実装依存。
表中の「名前空間」の項目は、パーサが要素や属性の名前空間の情報を渡すかどうかを表す。この機能がなくても自力で名前空間を調べることは可能だが、その分のコード(名前空間テーブルとそのスタックの管理)がアプリケーション側に必要になる。逆に言うと名前空間サポートのある API を持ったパーサはその分コードサイズが増えており、パース処理も若干重くなるのが普通である。
現在のところ XML 1.0 に完全に準拠した軽量パーサはほとんどない。多くのパーサは何らかの制限付きのサブセット仕様を満たすものになっており、妥当性検証はもちろんのこと XML 1.0 で定められた non-validating パーサの仕様にも厳密には従っていない。テスト対象とした各パーサの XML 1.0 の仕様に対する対応状況を 表4にまとめた。
パーサ名 | 混在内容 | 空要素 | CDATA セクション | コメント | 属性 | 文字参照 | 定義済実体 | 内部実体 | 外部実体 | デフォルト 属性 |
---|---|---|---|---|---|---|---|---|---|---|
kXML2 | ○ | ○ | ○ | ○ | ○ | ○ | ○ | △*1 | × | × |
MXP1 (min) | ○ | ○ | ○ | ○ | ○ | ○ | ○ | △*1 | × | × |
MXP1 (std) | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | × | ○ |
MinML1 | △*2 | ○ | ○ | ○ | ○ | ○ | ○ | × | × | × |
MinML2 | △*2 | ○ | ○ | ○ | ○ | ○ | ○ | × | × | × |
TinyXML | ○*3 | ○ | ○ | ○ | ○ | ○ | ○ | ○ | △*4 | △*5 |
NanoXML/Lite | × | ○ | ○ | ○ | ○ | ○ | ○ | × | × | × |
Min | × | × | × | × | × | ○ | × | × | × | × |
*1 アプリケーション側で実体を定義するコードが必要。
*2 原則として空白のみのテキストノードを捨てる。
*3 バグフィックスパッチを適用した場合。元々はタグの後ろに続く空白を無条件に捨てるというバグがある。
*4 アプリケーション側で外部実体を解決するコードが必要。
*5 デフォルト値は自動的には適用されないが、ATTLIST のイベントが来るので自力で実装すれば可能。
まず、ほとんどの軽量パーサは DTD の内部サブセットを一切解釈しない。non-validating パーサは妥当性検証はしないが、DTD の内部サブセットがあればそれをパースして内部実体の置換とデフォルト属性の設定を行うことが要求される。
軽量パーサにとってこれは負担になるので XML Pull API などではこの機能をオプションとしている。内部サブセットのある文書を扱うことは比較的まれであるし、デフォルト属性の効果は元々 DTD を参照しない XML データを扱うためにアプリケーション側でハードコードされることが多いので、実際にはこの制限はあまり障害にはならない。よって以下ではこの種のパーサを準フルセットパーサと呼ぶことにする。
文書に対してある種の機能を使わないことを要求するパーサもある。以下この種のパーサをサブセットパーサと呼ぶ。サブセットパーサの要求には、例えば混在内容(要素内容で、文字列と子要素が混ざったもの)を許さないというものがある。混在内容は XHTML のような文書指向の文書フォーマットでは多用されるが、データ指向の文書フォーマットでは全く使わない場合も多い。例えば住所録フォーマットの ContactXML [cxml] などがそれに該当する。
この種の制限で最も厳しいものは文書が XML のサブセット仕様である Minimal XML に準拠することを求めるものである。Minimal XML は基本的に開始タグと終了タグと文字参照しか扱わないため、これを要求するパーサでは通常の XML データはまず扱えない。通常の XML データを 機械的に Minimal XML に変換することは可能であるが、一般には、専用の DTD と運用規則(コメントさえも使えないので)の元で作成されるデータのみを扱うことになる。このような厳しい制限と引き替えにコンパクトで高速なパーサの実装が得られる。
J2ME 環境では通常の Java 環境と異なり、利用できるエンコーディングに制限がある。特に日本の携帯電話の場合、基本的にはシフトJIS (SJIS) と ASCII (US-ASCII) しかサポートしていない(iアプリの場合は SJIS のみ)。XML パーサも一部を除いて環境のサポートするエンコーディングしか扱えない。また軽量パーサの場合は XML の encoding 宣言に記述される IANA のエンコーディング名を適切な Java のエンコーディング名に変換するようなこともしない。
よって、通常はパース前にあらかじめ SJIS で Reader を作成しておきそれをパーサに渡してパースするという手順が望ましい。それでも敢えて InputStream を使用してパーサのエンコーディング検出機能を使う場合、どこまであてにできるかを表5にまとめた。
パーサ名 | UTF-16/UTF-8 自動検出 | encoding宣言の扱い | デフォルトの動作 | ||
---|---|---|---|---|---|
検出の可否 | UTF-16 読み込み | UTF-8 読み込み | |||
kXML2 | ○ | 環境依存 | 環境依存 | InputStreamReader のコンストラクタにそのまま渡す | UTF-8 を使用 |
MXP1 | × | - | - | 一切扱わない | エラー |
MinML1 | × | - | - | 一切扱わない | 環境のデフォルトエンコーディングを使用 |
MinML2 | × | - | - | 一切扱わない | 環境のデフォルトエンコーディングを使用 |
TinyXML | ○ | ○ | ○ | ASCII, UTF-8, UTF-16系以外は検出された時点でエラー | UTF-8 を使用 |
NanoXML/Lite | - | - | - | 一切扱わない | Reader からのみパースする |
Min | ○ | ○ | ○ | XML宣言があるとエラー | UTF-8 を使用 |
表から分かるように一般のパーサと違い、軽量パーサでは encoding 宣言自体を扱わない場合が多い。今回テストしたパーサの中では kXML2 のみが encoding 宣言を扱うが、宣言された値をそのまま InputStreamReader のコンストラクタに渡すため、SJIS (これは IANA 名ではない)しかサポートしない環境では事実上使えない。
なお一部のパーサ(例えば TinyXML と Min)は自前で UTF-16 系や UTF-8 の Reader を実装しているため、これらをサポートしない J2ME 環境でも UTF-16 や UTF-8 の XML データをパースできる。
テスト対象のパーサについて携帯電話実機の J2ME 環境で簡単なベンチマークテストを実施した。テスト内容は 10KB 程度の XML データをパースし、要素と属性と文字の数をカウントするというものである。
テストの手順は以下の通りである。
テストデータはベンチマークアプリケーションの JAR ファイル内のリソースからあらかじめ適切なエンコーディングを設定して作成した InputStreamReader を介して読み込んだ。ただし TinyXML については Reader からパースができないので InputStream から読み込んだ。
テストデータは三種類用意した。その内容を表6にまとめた。
ファイル名 | サイズ | 文書型 | 符号化方式 | 要素数/属性数/文字数 | マークアップ密度 | 備考 |
---|---|---|---|---|---|---|
svg1 | 10143 | SVG 1.0 | us-ascii | 93/473/781 | 92% | |
xhtml1 | 10223 | XHTML 1.0 | us-ascii | 130/53/7665 | 26% | XML 1.0 仕様書の冒頭部分を切り出したもの。 |
xhtml2 | 9626 | XHTML 1.0 | Shift_JIS | 130/53/4293 | - * | xhtml01.htmlの邦訳。 |
* マルチバイトエンコーディングのファイルであり、他のファイルとは単純に比較できないので値は省略した。
表中の「マークアップ密度」は XML データの中でタグが占める割合を表す大まかな指標である。パーサの性能評価の場合、 1 - 文字内容のサイズ / ファイルサイズ で表される。一般にマークアップ密度の高いデータ程パーサに負荷がかかる。
なお、Minimal XML 準拠の Min に対しては Min に付属する minimizer というツール(を非ASCII文字の出力に対応させたもの)でテストファイルを Minimal XML に変換したものを使用した。
ベンチマークアプリケーションは CLDC/MIDP に準拠したもので、J-Phone の Java アプリとして動作するものである(ezplus での動作は未確認)。各パーサのクラスはパースに必要な最小限の構成でパッケージングした。詳細はベンチマークアプリケーションのソースコード[src]を参照されたい。
Java アプリ対応携帯電話である東芝 J-T51 上で実施したテスト結果は表7の通りである。各パーサのコードサイズ(パーサ実装のJARファイル換算のサイズ)も合わせて示した。
パーサ名 | コードサイズ*1 | パース時間 (ms) svg1/xhtml1/xhtml2 |
起動時間*2 (ms) | 結果 |
---|---|---|---|---|
kXML2 | 11.3KB | 3944/3700/3036 | 677 | ○ |
MXP1 | 17.8KB | 3034/2576/2298 | 1777 | ○ |
MinML1 | 13.6KB | 4484/4416/3558 | 1057 | △*3 |
MinML2 | 16.1KB | 5026/4708/3850 | 1448 | △*3 |
TinyXML | 9.8KB | 4402/3850/-*4 | 944 | ○ |
NanoXML/Lite | 6.8KB | 6160/-/- | 700 | △*3 |
Min | 14.8KB | 2400/2060/1926 *5 | 1528 | - |
*1 パーサを一緒にパッケージしたベンチマークアプリケーションのJARファイルサイズからパーサを含まないアプリケーションのJARファイルサイズを引いた値。
*2 初回起動時のパース時間から2回目以降のパース時間を引いた値。
*3 要素間の空白の数だけ文字数が少なくカウントされた。
*4 Shift_JIS に非対応なため xhtml2 はエラーになった。
*5 Minimizer で Minimal XML 化したテストファイルを使用。
Stefan Haustein 氏が開発した XML Pull API 準拠の準フルセットパーサ。オープンソースアプリケーションサーバ Enhydra のコミュニティが開発した kXML を元に軽量化を徹底し、J2ME 準拠の実装にしたものである。ツリー型 API 実装の kdom も含まれているが今回は評価していない。
パース速度は特に速くないが、起動時間が最も短かった。コードサイズも準フルセットパーサの中では最小の部類である。
バランスのとれた実装で携帯電話の環境に適している。改良やメンテナンスも頻繁に行われており今後についても期待できる。
Aleksander Slominski 氏が開発した XML Pull API 準拠のパーサ。準フルセット版とフルセット版(non-validation パーサ)がある。コンパクトで高速なパーサとして知られており、現在のところ世界最速と言われている。J2ME 環境よりも J2SE/EE 環境で高速に動くことを重視しているようで、そのままでは J2ME でビルドできない。テストに際してはわずかではあるが修正が必要だった。
パース速度は Min を例外とすると最も高速であった。kXML2 の 1.5 倍近い速度で体感可能なレベルの違いがある。しかし起動時間は最も長く、kXML よりも 1 秒も余計に待たされる。携帯電話のように起動・終了のサイクルが激しい環境では起動時間の長さが問題になるかもしれない。
コードサイズは今回テストした中では最大であった。17.8KB は十分小さいとも言えるが、30KB が上限のiアプリ環境では厳しいかもしれない。
高速性は魅力だが携帯電話の環境では少々バランスが悪い。改良やメンテナンスは頻繁に行われており今後については期待できるかもしれない。
John Wilson 氏が開発した組み込み用パーサで MinML1 が SAX1、MinML2 が SAX2 に準拠している。そのままでは J2ME でビルドが通らないが、J2ME 環境では使われない一部の機能を削除することでビルドできた。
元々 XML-RPC のような用途を想定しており、最近のバージョンまで混在内容を扱えなかった。その名残で、原則として要素並びの隙間にある空白のみの文字データは捨ててしまう。
MinML1 のパース速度はやや遅く、起動時間もやや長い、コードサイズもやや大きい、ということであまり見るべきところがないが、どうしても SAX API を使用したい場合は唯一の選択肢となる。MinML2 は SAX2 をサポートするが性能的には MinML1 よりさらに劣る。
メンテナンスは続いているがあまり活発ではない。現時点の最終更新は2001年11月である。
Tom Gibara 氏が開発したフルセットの non-validation パーサ。API は独自のイベント駆動型 API とツリー型 API があるが、後者は今回は評価していない。J2ME でビルドするためには多少修正が必要である。
パース速度や起動時間は MinML より少しましな程度であまり魅力的ではないが、フルセットパーサにも関わらずコードサイズは非常に小さく、サブセットパーサの NanoXML/Lite を除くと最小のパーサである。DTD をパースできる唯一の軽量パーサという点でもユニークな存在である。ただし DTD のパース機能を携帯電話用のアプリケーションで生かせる機会は稀であろう。
もっともフルセットパーサと言ってもその完成度には疑問が残る。空白の扱いにバグがある(これは修正した上でテストした)、Reader からパースできないので Shift_JIS のデータを扱えない、外部実体参照を解決するための API に不備があり相対パスの解決に失敗するなどの問題を抱えている(他にもあるかもしれない)。また、ATTLIST をパースしてもデフォルト属性がパース結果にストレートに反映されないのは厳密には仕様違反であろう。
そのような状態だが、2000年1月にバージョン0.7がリリースされて以降一切メンテナンスされていない。
Marc De Scheemaecker 氏が開発したサブセットパーサ。混在内容を扱えず、非空白文字の並びの中に開始タグがあると即エラーになる。API は独自のツリー構築型。J2ME でのビルドは多少修正が必要である。
SAX API をサポートしたフルセットの NanoXML/Java もあり、こちらも比較的軽量なパーサだが、J2ME でのビルドが困難だったため今回はテストしなかった。
パース速度は最も遅かった MXP1 の半分の速度である。起動時間は kXML と同程度に短くこの点は良い。しかしなにより素晴らしいのは 7KB を切るコードサイズである。パフォーマンス上の難点はあるが、唯一 503i で使える(相当に厳しいとは思うが) XML パーサという点で価値がある。
2002年4月に現在のバージョン(2.2.1)がリリースされた後、次のメジャーバージョンアップに向けての作業が進んでおり、今後が期待される。
Docuverse 社の開発した Minimal XML 準拠のサブセットパーサ。API は SAX1。「XML 1.0 への準拠性」で述べたように極めて限定された機能を持つかわりに高速軽量な実装になっている。J2ME でのビルドには多少修正が必要である。
パース速度は MXP1 を抜いて最速であった。起動時間は長く MXP1 と同程度。コードサイズは MXP1 よりは小さいがやや大きい。
最速と言っても MXP1 との差はそれほどではない。svg1 では約40%速いが、このテストファイルは属性が非常に多いため minimizer による属性の要素化の効果が大きいと思われる。属性の少ない xhtml1/xhtml2 では 20% 程度の差にとどまっている。この程度の速度向上と引き替えに Minimal XML の非常に強い制限を受け入れるべきなのか疑問である。
低機能なだけに現状で完成形なのかもしれないが、2000年4月の 1.0A5 リリース以降一切メンテナンスされていない。
今回の調査で J2ME 環境で XML パーサは使い物になるという見通しが立ったと考える。一般的な Shift_JIS の文書で 10KB を約 3 秒でパースできる(kXML2)ということはパース速度は約 28000 byte/sec であり、携帯電話の通信速度とほぼ同程度である。コードサイズについてはいわゆる第2世代の Java アプリケーションサービスではさほど障害にならない。ドコモの 503i については残念ながら厳しいが、NanoXML/Lite なら使える可能性がある。
今回テストしたパーサの中でベストチョイスを挙げるなら kXML2 がそれであろう。携帯電話の環境を考えた場合もっともバランスのとれたスペックを備えている。
アプリケーションのコードサイズが厳しい場合は、条件が許すなら NanoXML/Lite も有力な候補になるであろう。逆にコードサイズに余裕があるならパース速度優先で MXP1 を選択するのも良いだろう。ただし起動時間の長さには注意する必要がある。TinyXML は多機能なのにコードサイズが小さいという点で興味深いが、携帯電話の環境では多機能の部分があまり生きないし、完成度や将来性にも疑問があるので、自力でソースコードをメンテナンスできる人以外にはお奨めできない。
携帯電話で動作する XML パーサという厳しい要求に対して、意外にも多様な選択肢が存在することは喜ばしいことである。XML はモバイルアプリケーションにおいても有効なソリューションになるであろう。
今回のテストでは J2ME でビルドするため、およびサイズを縮小するために、パーサのソースコードを修正した。以下に修正方法の概要を示す。
アプリケーション側では ParserFactory を使わずに Parser 実装を直接 new する。
アプリケーション側では XMLReaderFactory を使わずに XMLReader 実装を直接 new する。
アプリケーション側では XmlPullParserFactory を使わずに XMLPullParser 実装を直接 new する。
readWhite();を、
if(inEpilog || inProlog) readWhite();に置き換える。
text.append("&#"); text.append(c); text.append(";");を、
text.append(ch[i]);に置き換える。