MAGIC V10解析(7)
再帰の処理をMAGICで・・・
今回はプログラムのタスク構造の取得です。これがMAGICで出来れば、あとのいわゆる「MAGIC解析」?は殆ど力作業なんじゃないかなぁ?
第三回目のときに、XMLスタイルシートを使って再帰的な構造のXMLを読み込んだと思いますが、それをMAGICのプログラムでやるにはどうするか・・・という話です。
方法はXSL(XMLスタイルシート)使ったのと全く同じように考えれば良いのですが、前回まで使用した「XML連携」は残念ながら使えません。従来方法・・・つまり、V9からの関数「XMLGet」を使うことになります(逆に言えば、スキーマ情報は無くてもOKということです)。
このあたりは将来的にはどうなるんでしょうか?ある部分は「XML連携」で、ある部分は従来方式というのは、Helpにも推奨されないようなことが書いてあったりして、ちょっと心配なところもありますね。
さて、前回解析したダミープログラムの主要な部分を抜き出したのが次のソースです。
見て頂ければお分かりのように、ネストされた「Task」タグを順にたどればOKです。「Task」以下のXMLの構造は全て同一になるので、「Header」タグやその他のタグの情報を順に取得していけば1プログラム内の全ての情報を取得することが可能です。
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<Application>
<ProgramsRepository>
<Programs>
<Task MainProgram="N">
<Header Description="タスク階層テスト" ISN_2="1" LastIsn="8">
</Header>
<Task MainProgram="N">
<Header Description="処理1" ISN_2="2" LastIsn="8">
</Header>
<Task MainProgram="N">
<Header Description="処理2" ISN_2="3" LastIsn="8">
</Header>
<Task MainProgram="N">
<Header Description="処理3" ISN_2="4" LastIsn="8">
</Header>
</Task>
</Task>
<Task MainProgram="N">
<Header Description="処理4" ISN_2="5" LastIsn="8">
</Header>
<Task MainProgram="N">
<Header Description="処理5" ISN_2="6" LastIsn="8">
</Header>
</Task>
</Task>
</Task>
<Task MainProgram="N">
<Header Description="処理6" ISN_2="8" LastIsn="8">
</Header>
</Task>
</Task>
</Programs>
</ProgramsRepository>
</Application>
(上記のソースは、骨格の部分のみを抜き出しています。更に、「Header」タグ中のいくつかの属性もカットしました。)
さて、このソースを解析するプログラムですが、今回は2本のプログラムを作成します。
ひとつめは、XMLをオブジェクトにロードし、開始位置であるところの最初のタスク(=プログラムのルートタスク)の場所「Application/ProgramsRepository/Programs/Task」を次の再帰プログラムに受け渡すプログラム。
もうひとつは、最初のプログラムから呼ばれ、タスク情報を取得していくプログラム。もし更にサブタスクが存在すれば、今度は自分自身を呼び出して順に処理する再帰的なプログラム。
今回はそれぞれのプログラムを、「タスク構造取得」、「タスク解析再帰」と名付けることとします。
プログラムの作成手順
プログラムの作成手順を以下に示します。箇条書きにしますので分かり辛いかもしれませんがご了解下さい。- タスク構造取得メインプログラム
最初に第一のプログラムを作成します。- タスク特性
- プログラム名:「タスク構造取得」
- タスクタイプ:バッチ
- タスク終了条件:「Yes」
- チェック時期:「A=後置」
- データビュー
データビューに以下のパラメータと変数を追加します。
パラメータで受け取ったidにより任意のプログラムソースを読めるようにします。
- パラメータ:「プログラムID」、数値4
- 変数:「XMLファイル名」、文字255、代入:式1「'%Source%\Prg_'&Trim(Str(A,'4'))&'.xml'」
- 変数:「XMLオブジェクト」、BLOB
- ロジック
ロジックにレコード後処理を追加します。
XMLをBlobに取り込んで、再帰用のプログラムをコールしますが、その際に、最初のタスク(ルートタスク)の位置をパラメータで渡してあげます。
- レコード後処理
- ブロック:条件:「FileExist (B)」
- 項目更新:C、値=式3:「File2Blb(B)」
- コールP:4(タスク解析再帰)、パラメータ1:式4:「0」、パラメータ2:式5:「'/Application/ProgramsRepository/Programs/Task'」
- ブロック:Else
- エラーW=警告:式6:「'プログラムリポジトリファイル「Prg_'&Trim(Str(A,'4'))&'.xml」が見つかりません。'」
- ブロック:End
- レコード後処理
- 入出力ファイル
入出力ファイルにXML読込の定義を記載します。- 名前:「XML」
- メディア:V=項目
- アクセス:R=読込
- 書式:N=なし
- 式/項目:C(XMLオブジェクト)
- タスク特性
- タスク構造取得サブプログラム
次に第二の再帰的なプログラムを作成します。 - タスク特性
- プログラム名:「タスク解析再帰」
- タスクタイプ:バッチ
- タスク終了条件:「Yes」
- チェック時期:「A=後置」
- データビュー
下記のパラメータと変数を追加します。
階層レベルは、ネストしているレベルを意味しますが、最初のプログラムで読み込んだXMLオブジェクトの位置を取得するのにも利用されます。ヘッダからタスクのIDと名前(それぞれ属性値)を取得し、変数にセットします。
- パラメータ:「階層レベル」、N=数値、3
- パラメータ:「XPATH」、A=文字、512
- 変数:「タスクID」、N=数値、3、代入:「Val(XMLGet (A+1,1,Trim(B)&'/Header','ISN_2'),'5')」
- 変数:「タスク名」、A=文字、30、代入:「XMLGet (A+1,1,Trim(B)&'/Header','Description')」
- 変数:「カウンター」、N=数値、3
- ロジック
レコード後処理と、タスク後処理を追加します。 - レコード後処理
エラー文を利用し、メッセージボックスにタスクIDと名前を表示させます。- エラー:W=警告、「Trim(Str(C,'3'))&'.'&D」
- エラー:W=警告、「Trim(Str(C,'3'))&'.'&D」
- タスク後処理
子タスクがあるかどうかを判定し、ある場合は、その個数分だけ更に自分自身を呼び出します。
Task[1]、Task[2]、Task[3]、・・・とpositionを指定します。
- 項目更新:E:カウンター、値:「E+1」
- ブロック:w=while式:「XMLExist (A+1,1,Trim(B)&'/Task['&Trim(Str(E,'3'))&']','')」
- コールプログラム:4(「タスク解析再帰」=自分自身)、パラメータ1:式:「A+1」、パラメータ2:式「Trim(B)&'/Task['&Trim(Str(E,'3'))&']'」
- 項目更新:E:カウンター、値:「E+1」
- ブロック:N=End
- 作成プログラムの組み込み
作成したプログラムは、前回作成したプログラム(リポジトリ一覧表示プログラム)を修正し、ホットキーによりコールできるようにします。- ロジックタブにイベントを追加します。
- 「Ctrl+H」キー→「E」キー→「S」キー→「↓」キー→「F5」キー→「Enter」キー
- 追加したイベントに、コールプログラムを追加します。
- 作成プログラム3(タスク構造取得)を指定、パラメータ1:一覧から「id」項目を選択
- ロジックタブにイベントを追加します。
- プログラムのテスト実行
一覧表示プログラムを起動し、任意のプログラムで「F5」キーを押すと、今回作成したプログラムが起動します。
メッセージボックスに順に取得したタスクの名称が表示されます。
改良・・・
ここまでくれば、あとは「お化粧」の世界です。タスクツリーを表示させてみましょう。
まず、メモリテーブルにタスク一覧取得用のテーブルを定義します。

「タスク解析再帰」プログラムは、次のような修正を行います。

- パラメータ「親ID」(N=数値、3)を追加します。
- 変数「タスクタイプ」(A=文字、1)を追加し、代入に「XMLGet (A+1,1,Trim(B)&'/Header/TaskType','val')」をセットします。
- C=登録リンクを追加します。
- レコード後処理のエラー行は無効にします。
- タスク後処理のコールプログラムにパラメータ3(変数項目「タスクID」)を追加します。
「タスク構造取得」プログラムの修正箇所は次のとおりです。
- レコード後処理のブロック文にアクション(DbDel ('5'DSOURCE,''))を追加します。
- コールプログラムのパラメータ3に式で「0」をセットするかスキップにチェックします。
結果は、ツリーコントロールを使用し、ネストしたタスクの構造を表示させてみましょう。「タスク一覧表示」というプログラムを作成します。
最後に、「プログラム一覧」のプログラムのイベントを修正し、完成です。

プログラムのソースをダウンロードできるようにしておきます。
MAGIC V10解析(1)
Size
8339
-
File type
text/html
MAGIC V10解析(2)
Size
8904
-
File type
text/html
MAGIC V10解析(3)
Size
9714
-
File type
text/html
MAGIC V10解析(4)
Size
9882
-
File type
text/html
MAGIC V10解析(5)
Size
10443
-
File type
text/html
MAGIC V10解析(6)
Size
9739
-
File type
text/html
V10HACKS_20070211.lzh
Size
21.8 kB
-
File type
application/x-lzh
- Category(s)
- dbMAGIC
