# 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 Format RESTXML.rpgle ```rpgle **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; ``` ### Fixed Format RESTXML.rpgle ```rpgle 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 ```