この 郵便番号検索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サービスは急速に拡大してきています。
ご自身でも調べてみてください。