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