RPG で XML 文書を処理する (SAX編 その 3)

RPG で XML 文書を処理する (SAX編 その 1)」や「RPG で XML 文書を処理する (SAX編 その 2)」で XML-SAX 命令の使い方を見てきましたが、インフォメーションセンターにも XML-SAX 命令の使い方のサンプルが載っているのを発見しましたので、こちらもここで紹介してみたいと思います。

http://publib.boulder.ibm.com/infocenter/iseries/v5r4/index.jsp?topic=/books_web/c0925086782.htm

このサンプルプログラムも「RPG で XML 文書を処理する (SAX編 その 1)」で見たように、日本語の CCSID 環境ではそのままで実行はできません。少なくとも現在のサポート状況では UCS-2 で処理する必要があります。

といってもそんなに大きな変更は必要ありません。XML-SAX 命令のオプション、戻される文字フィールドを UCS2 として定義すること、その文字数のカウントを変更することの三点です。


プログラム

↓が変更済みのものです。CCSID 5035 や CCSID 1399 の環境で動くことを確認しました。

ほぼ「RPG で XML 文書を処理する (SAX編 その 1)」での解説どおりの内容なので、あらためての細かい説明は必要ないでしょう。(同じように修正しています)
monitor / on-error でエラー処理を行っているあたり、前回までのサンプルプログラムよりは実際的かもしれませんね。

     H DEBUG(*XMLSAX)

     Fqsysprt   o    f  132        printer

      * The xmlRc subfield will be set to a non-zero value
      * if the XML-SAX operation fails because of an error
      * discovered by the parser

     DXMLSAXSMP1       Pr
     D   xmlFilE                     30A   const options(*varsize)
     DXMLSAXSMP1       Pi
     D   xmlFilE                     30A   const options(*varsize)

     D psds           SDS
     D   xmlRc                       10I 0  OVERLAY(psds:368)

     D qsysprtDs       DS           132

      * This data structure defines the type for the parameter
      * passed to the SAX handling procedure.

     D value_t         S             50A    VARYING
     D handlerInfo_t   DS                   QUALIFIED
     D                                      BASED(dummy)
     D   pValue                        *
     D   numAttendees                 5P 0
     D   name                               LIKE(value_t)
     D   company                            LIKE(value_t)
     D   alwExtraAttr                 1N
     D   handlingAttrs...
     D                                 N

      * Define a specific instance of the handlerInfo_t data
      * structure and the prototype for the handler
     D myHandlerInfo   DS                   LIKEDS(handlerInfo_t)
     D mySaxHandler    PR            10I 0
     D   info                               LIKEDS(handlerInfo_t)
     D   event                       10I 0  VALUE
     D   stringPtr                     *    VALUE
     D   stringLen                   20I 0  VALUE
     D   exceptionId                 10I 0  VALUE

      /free

          monitor;
             // Start XML parsing
             // Indicate that the handler should not allow
             // any unexpected attributes in the XML elements.
             myHandlerInfo.alwExtraAttr = *OFF;

            XML-SAX %HANDLER(mySaxHandler : myHandlerInfo)
                     %XML( XMLFile : 'doc=file ccsid=ucs2');
                 //  %XML('/home/myuserid/myxml.xml' : 'doc=file');

             // The XML parse completed normally
             // Results are passed back in the communication
             // area specified by the %HANDLER built-in function
             qsysprtDs = 'There are '
                       + %CHAR(myHandlerInfo.numAttendees)
                       + ' attendees.';

          on-error 00351;
             // The XML parse failed with a parser error.
             // The return code from the parser is in the PSDS.

            qsysprtDs = 'XML parser error: rc='
                       + %CHAR(xmlRc)
                       + '.';
          endmon;

          write qsysprt qsysprtDs;

          *inlr = '1';

      /end-free

     P mySaxHandler    B
     D                 PI            10I 0
     D   info                               LIKEDS(handlerInfo_t)
     D   event                       10I 0  VALUE
     D   stringPtr                     *    VALUE
     D   stringLen                   20I 0  VALUE
     D   exceptionId                 10I 0  VALUE

     D value           S                    LIKE(value_t)
     D                                      BASED(info.pValue)

     D chars           S          65535A    BASED(stringPtr)
     D ucs2            S          16383C    BASED(stringPtr)
     D ucs2Len         S             10I 0

      /free

       ucs2Len = stringLen / 2 ;

       select;

         // start parsing
         when event = *XML_START_DOCUMENT;
                clear info;

         // start processing an attendee, by indicating
         // that subsequent calls to this procedure should
         // handle XML-attribute events.
         when event = *XML_START_ELEMENT;
          //if %subst(chars : 1 : stringLen) = 'attendee';
            if %subst(ucs2 : 1 : ucs2len) = 'attendee';
               info.handlingAttrs = *ON;
               info.name = '';
               info.company = '';
               info.numAttendees += 1;
            endif;

         // display information about the attendee
         when event = *XML_END_ELEMENT;
          //if %subst(chars : 1 : stringLen) = 'attendee';
            if %subst(ucs2 : 1 : ucs2len) = 'attendee';
               info.handlingAttrs = *OFF;
               qsysprtDs = 'Attendee '
                           + info.name
                           + ' is from company '
                           + info.company;
               write qsysprt qsysprtDs;
            endif;

         // prepare to get an attribute value by setting
         // a basing pointer to the address of the correct
         // variable to receive the value
         when event = *XML_ATTR_NAME;
            if info.handlingAttrs;
             //if %subst(chars : 1 : stringLen) = 'name';
               if %subst(ucs2 : 1 : ucs2Len) = 'name';
                   info.pValue = %addr(info.name);
             //elseif %subst(chars : 1 : stringLen) = 'company';
               elseif %subst(ucs2 : 1 : ucs2Len) = 'company';
                   info.pValue = %addr(info.company);
               else;
                  // If the XML element is not expected to have
                  // extra attributes, halt the parsing by
                  // returning -1.
                  if not info.alwExtraAttr;
                     qsysprtDs = 'Unexpected attribute '
                              // + %subst(chars : 1 : stringLen)
                                 + %char(%subst(ucs2 : 1 : ucs2Len))
                                 + ' found.';
                     write qsysprt qsysprtDs;
                     return -1;
                  endif;
               info.pValue = *NULL;
               endif;
            endif;

         // handle an exception
         when event = *XML_EXCEPTION;
            qsysprtDs = 'Exception '
                       + %char(exceptionId)
                       + ' occurred.';
            write qsysprt qsysprtDs;
            return exceptionId;

         other;

            // If this is an attribute we are interested
            // in, the basing pointer for "value" has been
            // set to point to either "name" or "company"

            // Append each fragment of the value to the
            // current data
            if  info.handlingAttrs and info.pValue <> *NULL;
               if event = *XML_ATTR_CHARS or event = *XML_ATTR_PREDEF_REF;
                //value += %subst(chars : 1 : stringLen);
                  value += %char(%subst(ucs2 : 1 : ucs2Len));
               elseif event = *XML_ATTR_UCS2_REF;
                  ucs2Len = stringLen / 2;
                  value += %char(%subst(ucs2 : 1 : ucs2Len));
               endif;
            endif;

         endsl;

         return 0;

      /end-free

     P mySaxHandler    E

テスト用の XML ファイル

読み込み対象の XML ファイルです。

インフォメーションセンターに載っていた XML をそのまま CCSID 13488 の IFS ファイルにしました。(インフォメーションセンターのものをそのまま使用しましたので再録はしていません)

CCSID (「コード化文字セット ID」) が 13488 になっているのが確認できますね。

実行結果

テスト用に便利なので XML ファイルを引数として取るように変更しました。
以下のように XML ファイルを指定しての実行になります。

これがテスト用のファイルを使っての実行結果です。

実行結果について

実行結果の最後にエラーらしきものが出ていますが、これはサンプルプログラムの故意によるものです。

プログラムの最初で、XML-SAX ハンドラーの属性を、あらかじめ想定している XML 要素以外を検出した場合はエラーとする旨の設定としています。

             myHandlerInfo.alwExtraAttr = *OFF;

ハンドラープログラムの中で XML 要素の解析と処理を行っているのですが、'Attendee' と 'Company'、'name' 以外の要素であった場合、つまり想定している以外の要素が検出された場合はエラーメッセージを出して処理を終了してしまうようになっています。

あらかじめ決められていた要素以外に出くわした場合、alwExtraAttr (Allow Extra Attribute) がオフの設定であれば 'Unxpected attribute (要素名) found' というメッセージを出して終了するようになっていることがわかります。

                  if not info.alwExtraAttr;
                     qsysprtDs = 'Unexpected attribute '
                                 + %char(%subst(ucs2 : 1 : ucs2Len))
                                 + ' found.';
                     write qsysprt qsysprtDs;
                     return -1;
                  endif;

XML パーサーのエラーコードは以下のサイトなどに詳細が載っています。

http://publib.boulder.ibm.com/infocenter/iadthelp/v7r0/index.jsp?topic=/com.ibm.etools.iseries.pgmgd.doc/c0925076168.htm

また、XML パーサーのリターンコードは PSDS データ構造から取ってきています。

     D psds           SDS
     D   xmlRc                       10I 0  OVERLAY(psds:368)

[Top Pageに戻る]

Ads by TOK2