JKL.ParseXML クラスは、サーバ上の XML 形式ファイルをダウンロード〜解析して、
JavaScript オブジェクト(配列やマップ)に変換するライブラリです。
複雑な DOM 操作なく簡単なスクリプトで XML 形式ファイルを扱えるため、
Amazon など XML を出力する既存の Web サービスや、
CGI と連携することで ajax ページを手軽に構築できます。
IE・Firefox・Opera・Safari のクロスブラウザに対応しています。
XML を JSONのように手軽に扱える他、
JSON/CSV/LoadVars 形式ファイルなどのテキストファイルも利用可能です。
安定版アーカイブ:
jkl-parsexml-0.22.tar.gz
TAR.GZ
jkl-parsexml-0.22.zip
ZIP
最新版ソースコード:
http://svn.coderepos.org/share/lang/javascript/jkl/
SVN
※ prototype.js の Ajax クラスを使用している場合は、 XML.ObjTree クラス の利用もご検討ください。
なお、このページのサンプルスクリプトでは、デモのために他の JKL シリーズのライブラリを併用していますが、 実際には他のライブラリは不要で、jkl-parsexml.js はそれ単体のみで利用できます。
ここで利用しているサンプルXML:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <items> <item> <jcity>千代田区</jcity> <jlocal>千代田</jlocal> <jpref>東京都</jpref> <pref_cd>13</pref_cd> <zip_cd>1000001</zip_cd> </item> </items>
例えば、都道府県名(jpref)のアクセス方法:
<script type="text/javascript" src="jkl-parsexml.js"></script> <script><!-- var url = "zip.xml"; var http = new JKL.ParseXML( url ); var data = http.parse(); document.write( data["items"]["item"]["jpref"] ); // ["〜"] で連想配列にアクセス document.write( data.items.item.jpref ); // あるいは . 区切りでもOK【最も簡単】 // --></script>
XML ファイルを展開した結果の JavaScript オブジェクト全体:
{ items: { item: { jcity: "千代田区", jlocal: "千代田", jpref: "東京都", pref_cd: "13", zip_cd: "1000001" } } }
同期モード〜非同期モード、GETメソッド〜POSTメソッドを、
利用目的に応じてオプションで切り替えることが可能です。
同期モードでは、サーバからのHTTPレスポンスを待ってから結果を返します。
非同期モードでは、レスポンスを待たずにいったん終了し、
HTTPレスポンスが来た時点で指定された関数を呼び出します。
同期モードの方がプログラム記述は簡単になります、
いわゆる ajax の操作性(待たずに画面が更新されていくUI)については、
非同期モードの方が優れています。
GET メソッドと POST メソッドについては、HTML フォームの method 属性と同じです。
静的な(生成済の)XML ファイルを受信する場合には、GET メソッドを利用します。
CGI や WEB サービスを呼び出して検索結果など動的な XML を受信する場合には、
適宜 GET・POST メソッドを使い分けてください。(サーバ側の仕様に依る)
[DEMO]ボタンを押すと、サンプルソースを実際に実行します。
もっとも手軽な使い方は、同期モード(sync)のGETメソッドです。 DEMO
var url = "zip.xml";
var http = new JKL.ParseXML( url ); // JKL.ParseXMLオブジェクトを生成
var data = http.parse(); // ダウンロード〜解析する
alert( "jpref: "+data.items.item.jpref ); //(例)都道府県名を表示する
同期モードでは、 parse() メソッドの返り値に XML ファイルの解析結果が JavaScript オブジェクトとして返ります。
GETメソッドでなくPOSTメソッドを利用する場合は、
new JKL.ParseXMLコンストラクタの第2引数で
クエリ文字列を指定してください。
(第2引数を省略した時は GET メソッドとなる仕組みです)
DEMO
var url = "http://www.kawa.net/works/ajax/zip/ajaxzip.cgi";
var query = "zip=1000001";
var http = new JKL.ParseXML( url, query ); // JKL.ParseXMLオブジェクトを生成
var data = http.parse(); // ダウンロード〜解析する
alert( "jcity: "+data.items.item.jcity ); //(例)市町村名を表示する
ただし、
Opera では
POSTメソッドを使用できないようです。
Opera に対応する場合は、GETメソッドを利用してください。
(※Opera 8.5 以降では、POST メソッドも問題なく利用できます)
非同期モードでは、
XML解析処理の完了後に指定した関数が呼び出されます。
DEMO
サーバからの XML ファイルの到着を待たずにブラウザの描画・ユーザ操作が再開するので、
レスポンスの良い・快適な操作を実現できます。
いわゆるajaxです。(asynchronous)
parse 実行前に async メソッドでコールバック関数を登録してください。
このコールバック関数の第1引数としてXML ファイルの解析結果が渡されます。
var url = "zip.xml";
var http = new JKL.ParseXML( url ); // JKL.ParseXMLオブジェクトを生成
var func = function ( data ) { // 呼び出し先関数を定義する
alert( "jlocal: "+data.items.item.jlocal ); //(例)地名を表示する
}
http.async( func ); // 呼び出し先関数を指定する
http.parse(); // ダウンロード〜解析〜関数呼び出しする
また、JKL.ParseXML の第2引数でクエリ文字列を指定した場合は、 同期モードと同様に POSTメソッドに切り替わります。
JKL.ParseXML は通常、XML の階層構造をそのままマップ(連想配列)に展開しますが、 同じ子要素が複数回登場する場合は、デフォルトでは JavaScript 側への出力データは 自動的に配列化されます。
ここで利用しているサンプルXML:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <children> <girl>花子</girl> <boy>太郎</boy> <boy>次郎</boy> </children>
配列展開されたboyの『次郎』にアクセスする方法:
<script type="text/javascript" src="jkl-parsexml.js"></script> <script><!-- var url = "children.xml"; var http = new JKL.ParseXML( url ); var data = http.parse(); document.write( data["children"]["boy"][1] ); // ["〜"] で連想配列アクセスする document.write( data.children.boy[1] ); // あるいは . で並べてもOK // --></script>
XML ファイルを展開した結果全体のデータ構成: (boyが配列展開されている)
{ children: { girl: "花子", boy: [ "太郎", "次郎" ] } }
setOutputArrayElements() メソッドを利用すると、指定した要素は、値が配列として展開されます。
それ以外の要素は、配列でなく最初に登場した要素の値のみ展開されます。
複数の要素を配列展開させる場合は、各要素名を配列にして指定します。
var http = new JKL.ParseXML( url ); http.setOutputArrayElements( "boy" ); //『boy』だけを配列展開する http.setOutputArrayElements( ["boy"] ); //『boy』だけを配列展開する http.setOutputArrayElements( ["boy", "girl"] ); //『boy』と『girl』の2要素とも配列展開する http.setOutputArrayElements( [] ); // どの要素も配列展開しない(初登場優先) http.setOutputArrayElements( "*" ); //『children』『boy』『girl』全て配列展開する http.setOutputArrayElements( "boy", "girl" ); // 誤り。配列で括ってください
setOutputArrayNever() メソッドを利用すると、重複を無視して最初に登場した要素の値のみ展開されます。
この例では、『次郎』が消えてしまいますが、スクリプトは簡単になります。
{ children: { girl: "花子", boy: "太郎" } }
setOutputArrayAll() メソッドを利用すると、全ての要素が配列として展開されます。
データ構成は冗長になりますが、データ消失もありません。
{ children: [ { girl: [ "花子" ], boy: [ "太郎", "次郎" ] } ] }
子要素の登場数によって自動判別します。(デフォルト)
XML ファイルの内容によってデータ階層数が変わってしまうため、
JavaScript 中で typeof などで確認しながら処理する必要があります。
{ children: { girl: "花子", boy: [ "太郎", "次郎" ] } }
JKL.ParseXML には、デフォルトの XML 形式ファイル処理以外にも、
テキストファイルや、
JSON 形式ファイルを処理するためのサブクラスが用意されています。
これらのサブクラスを利用することで、
JKL.ParseXML を『クロスブラウザ対応の HTTP 通信ライブラリ』として利用できます。
※各サブクラスが、Safari でも利用できるようになりました!
IE6・Firefox・Opera 8.5・Safari 2.0 で稼動します。
任意のテキストファイルの内容をそのまま文字列として受信するサブクラスです。 DEMO
var url = "hello.txt"; var http = new JKL.ParseXML.Text( url ); var data = http.parse(); alert( "data: "+data ); //『data: Hello, World!!』
使い方は、JKL.ParseXML クラス本体と同様です。
new() コンストラクタで、URL と POST 用のクエリ変数を指定できます。
parse() メソッドの返り値として、テキストファイルの中身がそのまま文字列として入ります。
内部処理としては XMLHttpRequest の responseText プロパティを利用しているだけで、
パース処理などは特に何もしていませんが、メソッド名の統一のため parse() となっています。
テキストファイルの文字コードは UTF-8 をご利用ください。(Safari 2.0対応)
JSON サブクラスは、サーバから JSON 形式ファイルを受け取る際に便利です。 DEMO
こちらも、使い方は JKL.ParseXML クラス本体と同じです。
parse() メソッドの返り値として、JSON 形式ファイルの内容そのままの
JavaScript オブジェクトが取り出せます。
var url = "zip-utf8.json"; var http = new JKL.ParseXML.JSON( url ); var data = http.parse(); alert( "jlocal: "+data.items.item.jlocal ); //『jlocal: 千代田』
なお、内部処理としては eval により JSON データを展開していますので、 サーバ上の JSON データは信頼できる内容にしておく必要があります。 (任意の JavaScript コードを実行できてしまうため)
『ajax』とは本来、非同期かつ XML 利用がもともとの形態のハズですが、 『広義の ajax』としては、同期・JSON 利用も含まれると考えられています。
CSV ファイルの内容を2次元配列として取り込みます。 DEMO
var url = "zip-utf8.csv"; var http = new JKL.ParseXML.CSV( url ); var data = http.parse(); alert( "data[1][6]: "+data[1][6] );
例えば、43行15列からなるCSVファイルの場合、
左上のセルの値は data[0][0]、
右下のセルの値は data[42][14] として取り出します。
上のサンプルは [1][6] ですから、2行目の7列目を取り出しています。
補足事項:
各セルは "〜" で囲まれていても構いません。(セル内に , を使う場合など)
セル内に " を入れる場合は、『"』1文字につき『""』と記載します。(Excel等の仕様)
HTML ページ側の文字コードは限定されません。
(HTML自体は、UTF-8でもShift_JISでもOK)
CSVmap サブクラスでは、 CSV ファイルの1行目をタイトル行として、 2行目以降をマップ化(連想配列化)します。 DEMO
var url = "zip-utf8.csv"; var http = new JKL.ParseXML.CSVmap( url ); var data = http.parse(); alert( "data[0].pref: "+data[0].pref );
実データ1行目(=CSVファイルの2行目)が data[0] のマップ(連想配列)に入ります。
例えば、1列目のカラム名は jis、15列目のカラム名は flag6 ですから、
実データ1行目のセルの値は data[0].jis または data[0]["jis"]、
右下のセルの値は data[41].flag6 または data[41]["flag6"] として取り出せます。
エクセル等で作成する CSV ファイルは、UTF-8 コードでなくて Shift_JIS コードになっています。
各サブクラスで利用できるのは基本的に UTF-8 専用となりますので、
Shift_JIS コードの CSV ファイルを利用する場合は
文字化けを防ぐために、サーバ上の .htaccess に以下の設定が必要になります。
CSV ファイルと同じディレクトリ(または上位階層)の .htaccess に下記の内容を設定してください。
AddType text/plain;charset=Shift_JIS .csv
上記の .htaccess を設置することにより、 IE6・Firefox・Opera 8.5 とも Shift_JIS の CSV ファイルが利用できるようになります。
ただし、Safari 2.0 だけは、テキストファイルの文字コードの変換を行わないため、
文字化けが発生します。
Safari 2.0 にも対応したい ajax アプリの場合は、
UTF-8 のテキストファイルか、XML ファイルをご利用ください。
なお、CSV ファイル本来の MIME タイプは text/comma-separated-values です。 しかし、これは Opera で文字コード変換に失敗して文字化けする場合があるため、 text/plain とすることをオススメします。
# Opera で文字コード判別に失敗する例(利用できず) AddType text/comma-separated-values;charset=Shift_JIS .csv
ActionScriptの LoadVarsクラスや loadVariables関数 で 利用される application/x-www-form-urlencoded 形式のテキストファイルの内容を連想配列として取り込みます。 DEMO
var url = "zip-utf8.vars"; var http = new JKL.ParseXML.LoadVars( url ); var data = http.parse(); alert( "data.jlocal: "+data.jlocal );
application/x-www-form-urlencoded 形式とは、CGI の GET 送信における ? 以下の形式と同じです。 以下のように、キーと値を = で区切ったものを、& で並べます。
zip_cd=1000001&pref_cd=13&jpref=東京都&jcity=千代田区&jlocal=千代田
『=』の文字自体は『%3D』、『&』は『%26』とエスケープしておく必要があります。 文字コードは UTF-8 です。
『JKL.ParseXML.LoadVars』という長ったらしい意味不明なサブクラス名になっていますが、 要は、FLASH 用に構築された CGI などを、 そのまま JavaScript から流用できるのがポイントです。
大きなXMLファイルを読み込む場合など、
XMLファイルの全体を一度に JavaScript オブジェクトに変換せずに
自前で DOM 操作を行って処理したい場合があります。
その場合には、DOM サブクラスをご利用ください。
DEMO
var url = "zip.xml"; var http = new JKL.ParseXML.DOM( url ); var dom = http.parse(); alert( "nodeName: "+dom.nodeName ); //『nodeName: items』
こちらも、使い方は JKL.ParseXML クラス本体と同じです。
parse() メソッドの返り値として、XML ファイルを JavaScript オブジェクト展開した結果ではなく、
XML ファイルの documentElement そのもの(DOM)が取り出せます。
0.12以前の全てのバージョンのJKL.ParseXMLには、
TEXT_NODE の処理にバグがありました。thanks to KT
現在のバージョンでは修正してありますので、
更新をお願いいたします。
しかし、何らかの事情で今後も 0.10 以前の旧バージョンを利用し続けたい場合は、 jkl-parsexml.js ソースの下記の1行を書き換えてください。
修正前
if ( elem.nodeType == 3 || elem.nodeType == 4 ) {
var bool = elem.nodeValue.match( /[^\u0000-\u0040]/ );
if ( bool == null ) return; // ignore white spaces
修正後
if ( elem.nodeType == 3 || elem.nodeType == 4 ) {
var bool = elem.nodeValue.match( /[^\x00-\x20]/ );
if ( bool == null ) return; // ignore white spaces
Safari では [^\u0000-\u0020] でなく [^\x00-\x20] と書く必要があるんですね。
これはバージョン 0.14 で対応しました。正規表現の Unicode 表記ができないのか?
JKL.ParseXML はフリーウェアです。(修正 BSD ライセンス)
商用・非商用を問わず、ご利用いただけます。
ソースコードの改変も構いませんが、
ソース内の Copyright 行については削除できません。
なお、ご利用に際して、必ずしも事前にメール等でご連絡いただく必要はありません。
多くの商用サイト・イントラサイト・個人サイトなどでご利用いただいております。