この 郵便番号検索API サイト ( http://zip.cgis.biz/
) では郵便番号をパラメータとして
このサイトに要求すると住所名が検索されて XML として戻されます。
つまりこのサイトは郵便番号検索の Webサービスを提供しているサイトです。
例えば、
http://zip.cgis.biz/xml/zip.php?zn=5700028
のように郵便番号 ( 570-0028
)をパラメータとして要求すると結果として次のような XML が戻ってきます。
<?xml version="1.0" encoding="utf-8" ?> - <ZIP_result> <result name="ZipSearchXML" /> <result version="1.01" /> <result request_url="http%3A%2F%2Fzip.cgis.biz%2Fxml%2Fzip.php%3Fzn%3D5700028" /> <result request_zip_num="5700028" /> <result request_zip_version="none" /> <result result_code="1" /> <result result_zip_num="5700028" /> <result result_zip_version="0" /> <result result_values_count="1" /> - <ADDRESS_value> <value state_kana="オオサカフ" /> <value city_kana="モリグチシ" /> <value address_kana="ホンマチ" /> <value company_kana="none" /> <value state="大阪府" /> <value city="守口市" /> <value address="本町" /> <value company="none" /> </ADDRESS_value> </ZIP_result>
従って、このXML から住所名を取り出してやればよいことになります。
しかし問題は
という技術です。
これらを簡単に可能にしてくれるのが EnterpriseServer の XML パーサー ( XML_PARSE
) です。
XML パーサーとは XML を解析してプログラムが扱うことができる DOM
( 文書化モデル= Document Object Model
)に
分解してくれるソフトウェアのことです。
EnterpriseServer の XML パーサーは XML_PARSE という名前のコマンドとして提供されています。
XML_PARSE は次のことを行います。
この XML パーサーはまた次の点において優れています。
EnterpriseServer の XML パーサー なら動作は極めてシンプルです。
DOM
とは一体、どのような構造になっているのか紹介します。
<?xml version="1.0" encoding="utf-8" ?> - <ZIP_result> <result name="ZipSearchXML" /> <result version="1.01" /> <result request_url="http%3A%2F%2Fzip.cgis.biz%2Fxml%2Fzip.php%3Fzn%3D5700028" /> <result request_zip_num="5700028" /> <result request_zip_version="none" /> <result result_code="1" /> <result result_zip_num="5700028" /> <result result_zip_version="0" /> <result result_values_count="1" /> - <ADDRESS_value> <value state_kana="オオサカフ" /> <value city_kana="モリグチシ" /> <value address_kana="ホンマチ" /> <value company_kana="none" /> <value state="大阪府" /> <value city="守口市" /> <value address="本町" /> <value company="none" /> </ADDRESS_value> </ZIP_result>
これを展開した DOM は次にようになります。
XMLタグ 001 |
XMLタグ 002 |
XMLタグ 003 |
・・・ | XMLタグ 010 |
KEY レベル |
属性数 | 属性 001 |
属性 002 |
・・・ | 属性 010 |
テキスト |
---|---|---|---|---|---|---|---|---|---|---|---|
ZIP_result | |||||||||||
ZIP_result | result | 1 | 2 | name="ZipSearchXML" | |||||||
ZIP_result | result | 1 | 2 | version="1.01" | |||||||
: | |||||||||||
ZIP_result | ADDRESS_value | value | 1 | 2 | state=" 大阪府 " | ||||||
ZIP_result | ADDRESS_value | value | 1 | 2 | city=" 守口市 " | ||||||
: |
DOM の DDS ソース
は次のとおりです。( ASNET.USR/QDDSSC(DOM)
)
0001.00 A****************************************************** 0002.00 A* DOM : DOCUMENT OBJECT MODEL FOR XML PARSER VER1.0 0003.00 A****************************************************** 0004.00 A* 20 階層下までの XML に分解する 0005.00 A* タグの名前は親タグをすべて上位に付加して 0006.00 A* N 番目の KEYXXN として登録されている。 0007.00 A* N 番目を示すのが KEYLVL である。 0008.00 A* タグに囲まれた値はタグの値として KEYVAL に 0009.00 A* 登録されている。 0010.00 A* 0011.00 A*-------------------------------------------------------------- 0012.00 A* XML は一般的に 0013.00 A* <MYTAG PRM001=AA PRM002=BBB>MYVALUE</MYTAG> 0014.00 A* の形式で保管されている。 0015.00 A* 0016.00 A* MYTAG: タグ名 KEY001 - KEY020 0017.00 A* PRM001=AA, PRM002=BBB: 属性 PRM001 - PRM020 0018.00 A* MYVALUE: 値 DOMTXT 0019.00 A*-------------------------------------------------------------- 0020.00 A** UNIQUE 0021.00 A R DOMREC TEXT('DOM レコード ') 0022.00 A* 0023.00 A KEY001 40O COLHDG('XML タグ 001') 0024.00 A KEY002 40O COLHDG('XML タグ 002') 0025.00 A KEY003 40O COLHDG('XML タグ 003') 0026.00 A KEY004 40O COLHDG('XML タグ 004') 0027.00 A KEY005 40O COLHDG('XML タグ 005') 0028.00 A KEY006 40O COLHDG('XML タグ 006') 0029.00 A KEY007 40O COLHDG('XML タグ 007') 0030.00 A KEY008 40O COLHDG('XML タグ 008') 0031.00 A KEY009 40O COLHDG('XML タグ 009') 0032.00 A KEY010 40O COLHDG('XML タグ 010') 0033.00 A* 0034.00 A KEYLVL 4S 0 COLHDG('KEY レベル ') 0035.00 A PRMSU 2S 0 COLHDG(' 属性の数 ') 0036.00 A* 0037.00 A PRM001 128O COLHDG(' 属性 001') 0038.00 A PRM002 128O COLHDG(' 属性 002') 0039.00 A PRM003 128O COLHDG(' 属性 003') 0040.00 A PRM004 128O COLHDG(' 属性 004') 0041.00 A PRM005 128O COLHDG(' 属性 005') 0042.00 A PRM006 128O COLHDG(' 属性 006') 0043.00 A PRM007 128O COLHDG(' 属性 007') 0044.00 A PRM008 128O COLHDG(' 属性 008') 0045.00 A PRM009 128O COLHDG(' 属性 009') 0046.00 A PRM010 128O COLHDG(' 属性 010') 0047.00 A* 0048.00 A DOMTXT 2048O COLHDG(' テキスト ') 0049.00 A VARLEN(255) 0050.00 A* 0051.00 A K KEY001 0052.00 A K KEY002 0053.00 A K KEY003 0054.00 A K KEY004 0055.00 A K KEY005 0056.00 A K KEY006 0057.00 A K KEY007 0058.00 A K KEY008 0059.00 A K KEY009 0060.00 A K KEY010
これで DOM は XML をシンプルなデータ・ベースに展開したものであることがおわかりでしょう ?
そもそも XML の本質とは 構造化されたツリー構造のデータ・ベース表現 であり、これは
System i が最も得意とする物理ファイルに過ぎません。
しかし多くの XML パーサーが XML を物理ファイルとは別のモノであると扱っているために
折角、データ・ベースに得意なはずの IBM ユーザーの理解を得られなくなってしまっています。
これは System i の OS400 プラットフォームでの XML関連の開発者が XML の本質を正しく
理解できていないからに過ぎません。
XML を上記の物理ファイルとしての DOM に展開してしまえば IBM ユーザーには、このDOM をどのようにして
扱うべきか説明は不要でしょう。
あるIBM ユーザーはこうして解説している私より優れた処理方法を編み出すかもしれないからです。
それでは RPG で書かれた CGI : GETZIP
のソースを紹介しましよう。
001.00 H NOMAIN BNDDIR('ASNET.COM/MAIN') DATEDIT(*YMD/) 002.00 F********** 郵便番号の検索 *********************************** 003.00 F* GETZIP : TYPE: 単票表示 言語 : RPG# VER 5.1 004.00 F********************************************************************** 005.00 FGETZIPH CF E SPECIAL PGMNAME('ASNET.COM/HTMLDVR') 006.00 F PLIST(HPARM) 007.00 F INFDS(INFDSF) 008.00 FDOM IF E K DISK EXTFILE(DOM_LIB) 009.00 F USROPN 010.00 F INFDS(INFDSX) 011.00 F********************************************************************** 012.00 013.00 F*--------------------------------------------------------------------- 014.00 F* CRTMOD=CRTWEBMOD QTEMP/GETZIP SRCFILE(ASNET.USR/QRPGLESRC) + 015.00 F* OPTION(*NOXREF *NOSECLVL *NOEXPDDS *NOSHOWCPY) + 016.00 F* DBGVIEW(*SOURCE) AUT(*ALL) 017.00 F* CRTPGM=CRTPGM CGIBIN/GETZIP MODULE(ASNET.COM/MAIN QTEMP/GETZIP) + 018.00 F* ACTGRP(*NEW) AUT(*ALL) 019.00 F* USER=QTMHHTTP 020.00 F* TYPE=RPG# 021.00 F* HTML=/AS400-NET.USR/PROJECT/GETZIP/DSPHEAD.HTM 022.00 F* HTML=/AS400-NET.USR/PROJECT/GETZIP/DSPDTA01.HTM 023.00 F* LIBL=CGIBIN QTRFIL QGPL QTEMP ASNET.COM 024.00 F* CALL=HTTP://218.44.135.18/CGI-BIN/GETZIP.PGM 025.00 F* TEXT= 商品マスターファイル 026.00 F* SESSION=*NO 027.00 F* KEEP-ALIVE=*NO 028.00 F* CCSID=5026 029.00 F* 作成日 :CRTDATE=2011/05/06 時刻 18:11:00 BY QTMHHTTP 030.00 F* 変更日 :CHGDATE=2011/05/06 時刻 18:11:00 BY QTMHHTTP 031.00 F*--------------------------------------------------------------------- 032.00 033.00 /COPY ASNET.USR/QRPGLESRC,PROTOTYP5# 034.00 D DSPHEAD_GO PR 035.00 D DSPDTA01_GO PR 036.00 D XML_PARSE PR 037.00 D ZIP 10A Vアツマオ 038.00 D ATTR PR 40A 039.00 D KEY 15A Vアツマオ 040.00 D HTM_FILE S 10A INZ('GETZIPH ') 041.00 D HTM_LIB S 10A INZ('*LIBL ') 042.00 D DOM_LIB S 21 INZ('QTEMP/DOM') 043.00 D HTM_DIR S 128A INZ('/AS400-NET.USR/PROJECT/- 044.00 D GETZIP') 045.00 D OPNERR C CONST('XML を取得できません。 ') 046.00 D NOREC C CONST('XML が空です。 ') 047.00 D CMD1 S 128A INZ('ASNET.COM/XML_PARSE PATH(- 0048.00 D ''http://zip.cgis.biz/xml- 0049.00 D /zip.php?zn=') 0050.00 D CMD2 S 128A INZ(''') OUTPUT(*OUTFILE) - 0051.00 D OUTFILE(QTEMP/DOM)') 0052.00 D CMD S 180A 0053.00 0054.00 D*( ファイル情報データ構造 ) 0055.00 D INFDSF DS 0056.00 D 512A 0057.00 D HTM_RECORD *RECORD 0058.00 D INFDSX DS 0059.00 D 512A 0060.00 D FILREC 156 159B 0 0061.00 D*( プログラム状況データ構造 ) 0062.00 D INFDSP SDS 0063.00 D 512A 0064.00 /COPY ASNET.USR/QRPGLESRC,INFDSP 0065.00 /COPY ASNET.USR/QRPGLESRC,HPARM 0066.00 0067.00 ********************************************************* 0068.00 P EVENT B EXPORT 0069.00 ********************************************************* 0070.00 D PI 0071.00 /FREE 0072.00 ON_CLICK('DSPHEAD': 'GO': %PADDR(DSPHEAD_GO)); 0073.00 ON_CLICK('DSPDTA01': 'GO': %PADDR(DSPDTA01_GO)); 0074.00 /END-FREE 0075.00 P E 0076.00 ********************************************************* 0077.00 P BEGIN B EXPORT 0078.00 ********************************************************* 0079.00 * 最初の画面を出力します。 0080.00 D PI 0081.00 C WRITE DSPHEAD 0082.00 P E 0083.00 0084.00 ********************************************************* 0085.00 P DSPHEAD_GO B EXPORT 0086.00 ********************************************************* 0087.00 * GO ボタンが押されたときの記述を行います。 0088.00 D PI 0089.00 C READ DSPHEAD 99 0090.00 C CALLP XML_PARSE(ZIPCODE) 0091.00 C OPEN DOM 99 0092.00 C *IN99 IFEQ *OFF 0093.00 C READ DOM 50 0094.00 C* 0095.00 C FILREC IFEQ *ZEROS 0096.00 C CALLP ALERTMSG(NOREC:'(KFLD)':'(KFLD)') 0097.00 C WRITE DSPHEAD 0098.00 C RETURN 0099.00 C END 0100.00 C* 0101.00 C EVAL STATE = ATTR('state') 0102.00 C EVAL STATE_KANA = ATTR('state_kana') 0103.00 C EVAL CITY = ATTR('city') 0104.00 C EVAL CITY_KANA = ATTR('city_kana') 0105.00 C EVAL OTHER = ATTR('address') 0106.00 C EVAL OTHER_KANA = ATTR('address_kana') 0107.00 C WRITE DSPDTA01 0108.00 C CLOSE DOM 0109.00 C ELSE 0110.00 C CALLP ALERTMSG(OPNERR:'(KFLD)':'(KFLD)') 0111.00 C WRITE DSPHEAD 0112.00 C END 0113.00 P E 0114.00 0115.00 ********************************************************* 0116.00 P XML_PARSE B EXPORT 0117.00 ********************************************************* 0118.00 * XML を WEB サービスで受信して QTEMP/DOM へ展開します * 0119.00 D PI 0120.00 D ZIP 10A Value 0121.00 C EVAL CMD = %TRIMR(CMD1) + ZIP + %TRIM(CMD2) 0122.00 C ' ' CHECKR CMD L 4 0 0123.00 C Z-ADD L CMDLEN 0124.00 C*------------------------------------------------------- 0125.00 C CALL 'QCMDEXC' 0126.00 C PARM CMD 0127.00 C PARM CMDLEN 15 5 0128.00 C*------------------------------------------------------- 0129.00 P E 0130.00 0131.00 ********************************************************* 0132.00 P ATTR B EXPORT 0133.00 ********************************************************* 0134.00 * DOM の指定された属性のものを抜き出します。 0135.00 D PI 40A 0136.00 D KEY 15A Value 0137.00 0138.00 D RTNVAL S 80A 0139.00 D AR S 1 DIM(128) 0140.00 0141.00 C CAT '=':0 KEY 0142.00 C ' ' CHECKR KEY L 4 0 0143.00 C *LOVAL SETLL DOM 0144.00 C DO *HIVAL 0145.00 C READ DOM 50 0146.00 C 50 LEAVE 0147.00 C KEY:L SCAN PRM001 P 4 0 50 0148.00 C *IN50 IFEQ *ON 0149.00 C ADD L P 0150.00 C ADD 1 P 0151.00 C 80 SUBST(P) PRM001:P RTNVAL 0152.00 C MOVEA(P) RTNVAL AR 0153.00 C Z-ADD 1 N 4 0 0154.00 C '"' LOOKUP AR(N) 50 0155.00 C 50 MOVE ' ' AR(N) 0156.00 C 50 MOVEA(P) AR RTNVAL 0157.00 C RETURN RTNVAL 0158.00 C END 0159.00 C END 0160.00 C MOVEL(P) '*ERROR*' RTNVAL 0161.00 C RETURN RTNVAL 0162.00 P E 0163.00 0164.00 ********************************************************* 0165.00 P DSPDTA01_GO B EXPORT 0166.00 ********************************************************* 0167.00 * GO ボタンが押されたときの記述を行います。 0168.00 D PI 0169.00 C READ DSPDTA01 99 0170.00 C WRITE DSPDTA01 0171.00 P E 0172.00 0173.00 ********************************************************* 0174.00 P END B EXPORT 0175.00 ********************************************************* 0176.00 * 最後の処理を記述します。 0177.00 D PI 0178.00 C CLOSE GETZIPH 0179.00 C CLOSE DOM 0180.00 P E
このわずか 180ステップ数のプログラム自身は難しいものではないはずです。
特に今回の DOM は非常に簡単であり、RUNQRY *NONE QTEMP/DOM
で DOM に
どのような値が書かれているかを見れば、
属性 001 name="ZipSearchXML" version="1.01" request_url="http%3A%2F%2Fzip.cgis.biz%2Fxml%2Fzip. request_zip_num="5700028" request_zip_version="none" result_code="1" result_zip_num="5700028" result_zip_version="0" result_values_count="1" state_kana="オオサカフ" city_kana="モリグチシ" address_kana="ホンマチ" company_kana="none" state=" 大阪府 " city=" 守口市 " address=" 本町 " company="none"
のように 属性値 001 ( PRM001
) に求める答えがすべて書かれていることがわかりますので
すべての DOM レコードを読み取って 属性値001 だけを調べればよいことになります。
DOM や XML がどのような構造をしているか等を全く考慮する必要もありません。
QTEMP/DOM
を
*LOVAL SETLL DOM DO *HIVAL READ DOM 50 : END
のようにして、すべて読み取って
KEY:L SCAN PRM001 P
のよにして、PRM001 に state=
というような文字列があるかどうかを調べればよいだけです。
このように RPG プログラムによって、こんなに簡単に XML を調べることができるのも
XML パーサーが DOM をデータ・ベースに変換してくれるからです。
しかも DOM というデータ・ベースに変換された後も XML の本質は維持されているのです。
コンパイルの前には コマンド: XML_PARSE
を次のように使って QTEMP/DOM を作成しておいてください。
XML_PARSE PATH('http://zip.cgis.biz/xml/zip.php?zn=5700085') OUTPUT(*OUTFILE) OUTFILE(QTEMP/DOM)
このコマンドを実行できたら
RUNQRY *NONE QTEMP/DOM
によってデータ・ベース QTEMP/DOM が正しく作成されたかどうかを確認してください。
RPG : GETZIP
は RPG# で書かれてしますので
CRTWEBMOD QTEMP/GETZIP SRCFILE(MYSRCLIB/QRPGLESRC) AUT(*ALL) CRTPGM CGIBIN/GETZIP MODULE(ASNET.COM/MAIN QTEMP/GETZIP) ACTGRP(*NEW) AUT(*ALL)
によって行います。
いろいろな郵便番号を入れて試してみてください。
「GO」ボタンを押した瞬間に GETZIP
は System i からインターネット経由で 郵便番号検索API のサイトら
接続しに行って結果の XML を受信します。
あなたの IBM System i 自身が初めてインターネット経由で他のサーバーに接続して会話した瞬間のはずです。
素晴らしいとは思いませんか ?
今回は URL の様子からすると PHP と対話したようですが、この方法でどのようなプログラムでも
インターネット経由であなたのプログラムは会話することができます。
郵便番号による住所検索だけでなく
など等 Google, Yahoo!, Amazon などでもビジネスに使える Webサービスは急速に拡大してきています。
ご自身でも調べてみてください。