RESTXML

This example program demonstrates the basic structure of an RPG program utilizing RPG API Express to consume a REST based XML web service via HTTP GET, and parse the response XML with event-based parsing.


 
     H DFTACTGRP(*NO) ACTGRP(*CALLER) BNDDIR('RXSBND')

      /copy QRPGLECPY,RXSCB

     D XmlHandler      PR
     D  pType                        10A   Value
     D  pXPath                     1024A   Value Varying
     D  pData                          *   Value
     D  pDataLen                     10I 0 Value

     D gParseDS        DS                  LikeDS(RXS_ParseDS_t)
     D gTransmitDS     DS                  LikeDS(RXS_TransmitDS_t)
     D ErrorDS         DS                  LikeDS(RXS_CatchThrowErrorDS_t)

     D gXmlResponse    S                   Like(RXS_Var64Kv_t)
     D gNameList       S                   Like(RXS_Var64Kv_t)
     D gCount          S             10I 0

      /free

       // Please note that the REST web service being consumed by this example program
       //   is not 100% available due to metering being performed on the
       //   "demo" account.  Usually you can make multiple attempts over time and
       //   get a proper response eventually.

       monitor;

         // Transmit

         RXS_ResetDS( gTransmitDS : RXS_DS_TYPE_TRANSMIT );
         gTransmitDS.URI = 'http://api.geonames.org/cities'
                         + '?north=44.1&south=-9.9&east=-22.4'
                         + '&west=55.2&lang=de&username=demo';
         gTransmitDS.LogFile = '/tmp/log.txt';
         gTransmitDS.HTTPMethod = RXS_HTTP_METHOD_GET;
         gXmlResponse = RXS_Transmit( *Omit : gTransmitDS );

         // Parse

         gCount = 0;
         RXS_ResetDS( gParseDS : RXS_DS_TYPE_PARSE );
         gParseDS.GlobalHandler = %Paddr( XmlHandler );
         RXS_Parse( gXmlResponse : gParseDS );

         // Output Parse Results as a Thrown Message

         RXS_ResetDS( ErrorDS : RXS_DS_TYPE_CATCHTHROWERROR );
         ErrorDS.MessageId = 'RXS9897';
         ErrorDS.MessageData = gNameList;
         ErrorDS.ThrowToCaller = RXS_YES;
         RXS_Throw( ErrorDS );


       on-error;

         RXS_Joblog('Unexpected error occurred. See previous messages.');

       endmon;

       *inlr = *on;

      /end-free

     P XmlHandler      B
     D XmlHandler      PI
     D  pType                        10A   Value
     D  pXPath                     1024A   Value Varying
     D  pData                          *   Value
     D  pDataLen                     10I 0 Value

     D base            s            256a   Varying
     D chgMe           s            256a   Varying

      /free

       base = '/geonames/geoname';
       select;

         when pXPath = '/geonames/>';
           if gCount > 0;
             gNameList += 'No more names!';
           endif;

         when pXPath = base + '/toponymName>';
           gCount += 1;
           gNameList += %char(gCount) + ': ';

         when pXPath = base + '/toponymName/>';
           gNameList += ', ';

         when pXPath = base + '/toponymName/';
           gNameList += RXS_STR( pData : pDataLen );

         // If the service is unavailable to the usage metering mentioned earlier,
         //   there will be XML data available for parsing per the below

         when pXPath = '/geonames/status@message';
           gNameList = RXS_STR( pData : pDataLen );

         when pXPath = '/geonames/status@value';
           gNameList += ' (' + RXS_STR( pData : pDataLen ) + ')';

         // The below code is for unused paths, but is included for clarity

         when pXPath = base + '/name/';
           chgMe = RXS_STR( pData : pDataLen );

         when pXPath = base + '/lat/';
           chgMe = RXS_STR( pData : pDataLen );

         when pXPath = base + '/lng/';
           chgMe = RXS_STR( pData : pDataLen );

         when pXPath = base + '/geonameId/';
           chgMe = RXS_STR( pData : pDataLen );

         when pXPath = base + '/countryCode/';
           chgMe = RXS_STR( pData : pDataLen );

         when pXPath = base + '/countryName/';
           chgMe = RXS_STR( pData : pDataLen );

         when pXPath = base + '/fcl/';
           chgMe = RXS_STR( pData : pDataLen );

         when pXPath = base + '/fcode/';
           chgMe = RXS_STR( pData : pDataLen );

       endsl;

      /end-free

     P                 E