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.
**FREE
Ctl-Opt ActGrp(*Caller) BndDir('RXSBND') Option(*NoDebugIO)
  Text('Ex - RESTXML');
/COPY QRPGLECPY,RXSCB
Dcl-Ds TransmitDS LikeDS(RXS_TransmitDS_t);
Dcl-Ds ParseDS LikeDS(RXS_ParseDS_t);
Dcl-Ds ErrorDS LikeDS(RXS_CatchThrowErrorDS_t);
Dcl-S XML Like(RXS_Var64Kv_t);
Dcl-S gNameList Like(RXS_Var64Kv_t);
Dcl-S gCount Int(10);
// 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( TransmitDS : RXS_DS_TYPE_TRANSMIT );
  TransmitDS.URI = 'http://api.geonames.org/cities'
                 + '?north=44.1&south=-9.9&east=-22.4'
                 + '&west=55.2&lang=de&username=demo';
  TransmitDS.LogFile = '/tmp/log.txt';
  TransmitDS.HTTPMethod = RXS_HTTP_METHOD_GET;
  XML = RXS_Transmit( *Omit : TransmitDS );
  // Parse
  reset gCount;
  reset gNameList;
  RXS_ResetDS( ParseDS : RXS_DS_TYPE_PARSE );
  ParseDS.GlobalHandler = %Paddr( XmlHandler );
  RXS_Parse( XML : ParseDS );
  // 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;
return;
Dcl-Proc XmlHandler;
  Dcl-Pi *N;
    pType Char(10) Value;
    pXPath VarChar(1024) Value;
    pData Pointer Value;
    pDataLen Int(10) Value;
  End-Pi;
  Dcl-S base VarChar(256);
  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 ) + ')';
  endsl;
End-Proc;
     
     H DFTACTGRP(*NO) ACTGRP(*CALLER) BNDDIR('RXSBND') OPTION(*NODEBUGIO)
     H TEXT('Fixed Format Ex - RESTXML')
      /COPY QRPGLECPY,RXSCB
     D XmlHandler      PR
     D  pType                        10A   Value
     D  pXPath                     1024A   Value Varying
     D  pData                          *   Value
     D  pDataLen                     10I 0 Value
     D TransmitDS      DS                  LikeDS(RXS_TransmitDS_t)
     D ParseDS         DS                  LikeDS(RXS_ParseDS_t)
     D ErrorDS         DS                  LikeDS(RXS_CatchThrowErrorDS_t)
     D XML             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( TransmitDS : RXS_DS_TYPE_TRANSMIT );
         TransmitDS.URI = 'http://api.geonames.org/cities'
                        + '?north=44.1&south=-9.9&east=-22.4'
                        + '&west=55.2&lang=de&username=demo';
         TransmitDS.LogFile = '/tmp/log.txt';
         TransmitDS.HTTPMethod = RXS_HTTP_METHOD_GET;
         XML = RXS_Transmit( *Omit : TransmitDS );
         // Parse
         reset gCount;
         reset gNameList;
         RXS_ResetDS( ParseDS : RXS_DS_TYPE_PARSE );
         ParseDS.GlobalHandler = %Paddr( XmlHandler );
         RXS_Parse( XML : ParseDS );
         // 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;
       return;
      /END-FREE
     P XmlHandler      B
     D                 PI
     D  pType                        10A   Value
     D  pXPath                     1024A   Value Varying
     D  pData                          *   Value
     D  pDataLen                     10I 0 Value
     D base            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 ) + ')';
       endsl;
      /END-FREE
     P                 E