RXS_Convert()

RXS_Convert is a flexible subprocedure allowing you to perform many commonly required text and data conversions:

  • Convert to/from Base64 encoding
  • Convert to/from Base64Url encoding
  • Perform XML entity encoding/decoding to replace characters with the appropriate XML entities:
    • & to &
    • to "
    • ' to '
    • < to &lt;
    • > to &gt;
  • Encode or decode a URL’s querystring
  • Convert between CCSIDs (character sets)
  • Convert to uppercase or lowercase in a CCSID-aware manner - preferable to the common practice of using the %XLATE built-in function
  • General find & replace - you can specify your own characters/strings to perform replacements with. Essentially, this allows developers on IBM i OS 6.1 to access functionality similar to that of the %SCANRPL built-in function added in IBM i OS 7.1.

New in RXS 3.5.0:

Enhancements

  • Corrected an issue with Base64URL decoding where certain string lengths could not be accurately internally padding, causing decoding to fail.
  • Corrected an issue with Base64 and Base64URL decoding where a looping condition and/or decoding failure could occur when certain line break characters were present in the source string.

Subprocedure Prototype

D RXS_Convert...
D                 PR                  Extproc('RXS_Convert') Opdesc
D                                     Like(RXS_Var16Mv_t)
D                                     Rtnparm

The output of the specified conversion operation is returned.

D  pInput                             Like(RXS_Var16Mv_t) Const
D                                     Options(*Varsize:*Omit)

Field to hold the input of the selected conversion operation. You can pass a field smaller than 16M without any additional effort.

D  pDS                                Like(RXS_Var64K_t)
D                                     Options(*Varsize)

Holds settings which control how RXS_Convert operates. This parm can accomodate a number of possible data structures, listed below.

Valid Values:

  • RXS_ConvertCcsidDS_t
  • RXS_ConvertCaseDS_t
  • RXS_ConvertBase64DS_t
  • RXS_ConvertXMLEntitiesDS_t
  • RXS_ConvertUrlPercentDS_t
  • RXS_ConvertUserDefinedDS_t

Example Code


*-------------------------------------------------------------- * This example uses RXS_Convert() to encode data to Base64. * Base64 is commonly used to transfer binary data such as images * or cryptographic keys/hashes, but may be used on any data. * Important to note is that no CCSID conversion is performed on * the decoded data. If you are sending text, the receiver will * most likely not expect the data to be in EBCDIC, so you may * need to use RXS_Convert() to perform CCSID conversion prior * to performing Base64 encoding. *-------------------------------------------------------------- H DFTACTGRP(*NO) BNDDIR('RXSBND') ACTGRP(*CALLER) /copy QRPGLECPY,RXSCB D gRawData S Like(RXS_Var8Kv_t) D gBase64 S Like(RXS_Var8Kv_t) D gConvBase64DS DS LikeDS(RXS_ConvertBase64DS_t) /free gRawData = 'hello world!'; RXS_ResetDS( gConvBase64DS : RXS_DS_TYPE_CONVERTBASE64 ); gConvBase64DS.EncodeDecode = RXS_ENCODE; gBase64 = RXS_Convert( gRawData : gConvBase64DS ); // After encoding, gBase64 will contain: // aGVsbG8gd29ybGQh *INLR = *ON; /end-free

*-------------------------------------------------------------- * This example uses RXS_Convert() to decode Base64 encoded data. * Base64 is commonly used to transfer binary data such as images * or cryptographic keys/hashes, but may be used on any data. * Important to note is that no CCSID conversion is performed on * the decoded data. If you are receiving ASCII data that was * Base64 encoded, you may need to use RXS_Convert() to convert * it to a non-ASCII CCSID. *-------------------------------------------------------------- H DFTACTGRP(*NO) BNDDIR('RXSBND') ACTGRP(*CALLER) /copy QRPGLECPY,RXSCB D gBase64 S Like(RXS_Var8Kv_t) D gDecoded S Like(RXS_Var8Kv_t) D gConvBase64DS DS LikeDS(RXS_ConvertBase64DS_t) /free gBase64 = 'aGVsbG8gd29ybGQh'; RXS_ResetDS( gConvBase64DS : RXS_DS_TYPE_CONVERTBASE64 ); gConvBase64DS.EncodeDecode = RXS_DECODE; gDecoded = RXS_Convert( gBase64 : gConvBase64DS ); // After decoding, gDecoded will contain: // hello world! *INLR = *ON; /end-free

*-------------------------------------------------------------- * This example uses RXS_Convert() to encode XML entites in * character data. Note that because < and > would need to be * encoded, you cannot use RXS_Convert() to encode a complete * XML document. Each item being composed into an XML element * would need to be individually encoded. *-------------------------------------------------------------- H DFTACTGRP(*NO) BNDDIR('RXSBND') ACTGRP(*CALLER) /copy QRPGLECPY,RXSCB D gData S Like(RXS_Var8Kv_t) D gEncoded S Like(RXS_Var8Kv_t) D gConvXMLEntDS DS LikeDS(RXS_ConvertXMLEntitiesDS_t) /free gData = 'Bob & Mary'; RXS_ResetDS( gConvXMLEntDS : RXS_DS_TYPE_CONVERTXMLENTITIES ); gConvXMLEntDS.EncodeDecode = RXS_ENCODE; gEncoded = RXS_Convert( gData : gConvXMLEntDS ); // After encoding, gEncoded will contain: // Bob &amp; Mary *INLR = *ON; /end-free

*-------------------------------------------------------------- * This example uses RXS_Convert() to decode XML entites back * to the corresponding character data. If you have an XML * document with encoded characters, it is generally safe to use * RXS_Convert() on the entire XML document. One exception to this * is when the XML document contains a nested complete XML document * which frequently occurs with .Net SOAP services. In that scenario, * you need to first parse the inner XML document out, and then * perform conversion. Failure to do this may result in an invalid * XML document. *-------------------------------------------------------------- H DFTACTGRP(*NO) BNDDIR('RXSBND') ACTGRP(*CALLER) /copy QRPGLECPY,RXSCB D gXML S Like(RXS_Var8Kv_t) D gDecoded S Like(RXS_Var8Kv_t) D gConvXMLEntDS DS LikeDS(RXS_ConvertXMLEntitiesDS_t) /free gXML = '<xml>Bob &amp; Mary</xml>'; RXS_ResetDS( gConvXMLEntDS : RXS_DS_TYPE_CONVERTXMLENTITIES ); gConvXMLEntDS.EncodeDecode = RXS_DECODE; gDecoded = RXS_Convert( gXML : gConvXMLEntDS ); // After decoding, gDecoded will contain: // <xml>Bob & Mary</xml> *INLR = *ON; /end-free

*-------------------------------------------------------------- * This example uses RXS_Convert() to URL-encode data * (also known as 'percent encoding'). This is generally used * when passing values in a querystring within a URL. Note that * it is not possible to perform URL encoding on a complete URL * as many of the characters that make up a URL would be * erroneously converted. Instead, each value must be encoded * and concatenated to the URL. *-------------------------------------------------------------- H DFTACTGRP(*NO) BNDDIR('RXSBND') ACTGRP(*CALLER) /copy QRPGLECPY,RXSCB D gUrl S Like(RXS_Var1Kv_t) D gRawData S Like(RXS_Var8Kv_t) D gEncoded S Like(RXS_Var8Kv_t) D gConvUrlDS DS LikeDS(RXS_ConvertUrlPercentDS_t) /free gURL = 'http://www.example.com?key=' gRawData = 'hello world!'; RXS_ResetDS( gConvUrlDS : RXS_DS_TYPE_CONVERTURLPERCENT ); gConvUrlDS.EncodeDecode = RXS_ENCODE; gEncoded = RXS_Convert( gRawData : gConvUrlDS ); // After encoding, gEncoded will contain: // hello%20world%21 gURL += gEncoded; // gURL now contains: // http://www.example.com?key=hello%20world%21 *INLR = *ON; /end-free

*-------------------------------------------------------------- * This example uses RXS_Convert() to decode URL-encoded data * (also known as 'percent encoded'). *-------------------------------------------------------------- H DFTACTGRP(*NO) BNDDIR('RXSBND') ACTGRP(*CALLER) /copy QRPGLECPY,RXSCB D gEncoded S Like(RXS_Var8Kv_t) D gDecoded S Like(RXS_Var8Kv_t) D gConvUrlDS DS LikeDS(RXS_ConvertUrlPercentDS_t) /free gEncoded = 'key%3Dhello%20world%21'; RXS_ResetDS( gConvUrlDS : RXS_DS_TYPE_CONVERTURLPERCENT ); gConvUrlDS.EncodeDecode = RXS_DECODE; gDecoded = RXS_Convert( gEncoded : gConvUrlDS ); // After decoding, gDecoded will contain: // key=hello world! *INLR = *ON; /end-free

*-------------------------------------------------------------- * This example uses RXS_Convert() to perform CCSID conversion to * convert from ISO 8859-1 (CCSID 819) to EBCDIC (CCSID 37). *-------------------------------------------------------------- H DFTACTGRP(*NO) BNDDIR('RXSBND') ACTGRP(*CALLER) /copy QRPGLECPY,RXSCB D gData819 S Like(RXS_Var8Kv_t) D gData37 S Like(RXS_Var8Kv_t) D gConvCcsidDS DS LikeDS(RXS_ConvertCcsidDS_t) /free gData819 = x'48656C6C6F20576F726C6421'; RXS_ResetDS( gConvCcsidDS : RXS_DS_TYPE_CONVERTCCSID ); gConvCcsidDS.From = RXS_CCSID_ISO88591; gConvCcsidDS.To = RXS_CCSID_EBCDIC; gData37 = RXS_Convert( gData819 : gConvCcsidDS ); // After conversion, gData37 will contain: // Hello World! *INLR = *ON; /end-free

*-------------------------------------------------------------- * This example uses RXS_Convert() to convert lowercase characters * in gData to uppercase. This conversion happens in a CCSID * aware manner. For example, ü will be converted to Ü. This * is recommended over the common practice of using the %Xlate * function with A-Z/a-z constants. *-------------------------------------------------------------- H DFTACTGRP(*NO) BNDDIR('RXSBND') ACTGRP(*CALLER) /copy QRPGLECPY,RXSCB D gData S Like(RXS_Var8Kv_t) D gUppercase S Like(RXS_Var8Kv_t) D gConvCaseDS DS LikeDS(RXS_ConvertCaseDS_t) /free gData = 'Hello Günter'; RXS_ResetDS( gConvCaseDS : RXS_DS_TYPE_CONVERTCASE ); gConvCaseDS.UpperLower = RXS_UPPERCASE; gUppercase = RXS_Convert( gData : gConvCaseDS ); // After conversion, gLowercase will now contain // HELLO GÜNTER *INLR = *ON; /end-free

*-------------------------------------------------------------- * This example uses RXS_Convert() to convert uppercase characters * in gData to lowercase. This conversion happens in a CCSID * aware manner. For example, Ü will be converted to ü. This * is recommended over the common practice of using the %Xlate * function with A-Z/a-z constants. *-------------------------------------------------------------- H DFTACTGRP(*NO) BNDDIR('RXSBND') ACTGRP(*CALLER) /copy QRPGLECPY,RXSCB D gData S Like(RXS_Var8Kv_t) D gLowercase S Like(RXS_Var8Kv_t) D gConvCaseDS DS LikeDS(RXS_ConvertCaseDS_t) /free gData = 'HELLO GÜNTER'; RXS_ResetDS( gConvCaseDS : RXS_DS_TYPE_CONVERTCASE ); gConvCaseDS.UpperLower = RXS_LOWERCASE; gLowercase = RXS_Convert( gData : gConvCaseDS ); // After conversion, gLowercase will now contain // hello günter *INLR = *ON; /end-free

*-------------------------------------------------------------- * This example uses RXS_Convert() to replace instances of * specified characters or bytes with the provided replacements. * This was originally introduced to provide customers on IBM i * 6.1 with something similar to the %ScanRpl built-in function * which was only available on IBM i 7.1 or higher. Generally * if you are on IBM i 7.1 or higher, you can just use %ScanRpl. * The only advantage offered by using RXS_Convert() is that * up to 50 replacements may be specified, but each From and To * are limited to 32 bytes. *-------------------------------------------------------------- H DFTACTGRP(*NO) BNDDIR('RXSBND') ACTGRP(*CALLER) /copy QRPGLECPY,RXSCB D gInput S Like(RXS_Var8Kv_t) D gOutput S Like(RXS_Var8Kv_t) D gConvUsrDfnDS DS LikeDS(RXS_ConvertUserDefinedDS_t) /free gInput = 'This is a sample message'; RXS_ResetDS( gConvUsrDfnDS : RXS_DS_TYPE_CONVERTUSERDEFINED ); gConvUsrDfnDS.From(1) = 'sample'; gConvUsrDfnDS.To(1) = 'cool'; gConvUsrDfnDS.From(2) = 'message'; gConvUsrDfnDS.To(2) = 'message!'; gOutput = RXS_Convert( gInput : gConvUsrDfnDS ); // gOutput now contains: // This is a cool message! *INLR = *ON; /end-free

Data Structures

D RXS_ConvertBase64DS_t...
D                 DS                  Qualified Template Inz
 
D   ReturnedErrorInfo...
D                                     LikeDS(RXS_ReturnedErrorInfoDS_t) Inz
 
D   DataStructureType...
D                                5I 0 Inz(RXS_DS_TYPE_CONVERTBASE64)

Internal use only

D   OnErrorMessageType...
D                                5I 0
 
D   EncodeDecode                  N

Set to RXS_ENCODE or RXS_DECODE.

Valid Values:

  • RXS_ENCODE
  • RXS_DECODE

Default Value: RXS_DECODE

D   InputPointer...
D                                 *

Internal use only

D   InputLength                 10I 0

Internal use only

D   OutputPointer...
D                                 *

Internal use only

D   OutputLength                10I 0

Internal use only

D   Reserved                  2048A

Internal use only

D RXS_ConvertBase64DS_t...
D                 DS                  Qualified Template Inz
 
D   ReturnedErrorInfo...
D                                     LikeDS(RXS_ReturnedErrorInfoDS_t) Inz
 
D   DataStructureType...
D                                5I 0 Inz(RXS_DS_TYPE_CONVERTBASE64)

Internal use only

D   OnErrorMessageType...
D                                5I 0
 
D   EncodeDecode                  N

Set to RXS_ENCODE or RXS_DECODE.

Valid Values:

  • RXS_ENCODE
  • RXS_DECODE

Default Value: RXS_DECODE

D   PadEncodedOutput...           N   Inz(RXS_NO)

Set to RXS_YES or RXS_NO.

Valid Values:

  • RXS_YES
  • RXS_NO

Default Value: RXS_NO

D   InputPointer...
D                                 *

Internal use only

D   InputLength                 10I 0

Internal use only

D   OutputPointer...
D                                 *

Internal use only

D   OutputLength                10I 0

Internal use only

D RXS_ConvertCaseDS_t...
D                 DS                  Qualified Template Inz
 
D   ReturnedErrorInfo...
D                                     LikeDS(RXS_ReturnedErrorInfoDS_t) Inz
 
D   DataStructureType...
D                                5I 0 Inz(RXS_DS_TYPE_CONVERTCASE)
 
D   OnErrorMessageType...
D                                5I 0
 
D   Ccsid                       10I 0

The CCSID of the input string. Defaults to the CCSID of the current job.

D   UpperLower                    N

Set to RXS_UPPERCASE or RXS_LOWERCASE.

Valid Values:

  • RXS_UPPERCASE
  • RXS_LOWERCASE

Default Value: RXS_UPPERCASE

D   InputPointer...
D                                 *

Internal use only

D   InputLength                 10I 0

Internal use only

D   OutputPointer...
D                                 *

Internal use only

D   OutputLength                10I 0

Internal use only

D   Reserved                  2050A

Internal use only

D RXS_ConvertCcsidDS_t...
D                 DS                  Qualified Template Inz
 
D   ReturnedErrorInfo...
D                                     LikeDS(RXS_ReturnedErrorInfoDS_t) Inz
 
D   DataStructureType...
D                                5I 0 Inz(RXS_DS_TYPE_CONVERTCCSID)

Internal use only

D   OnErrorMessageType...
D                                5I 0
 
D   From                        10I 0

CCSID to convert the input data from.

D   To                          10I 0

CCSID to convert the input data to.

D   InputPointer...
D                                 *

Internal use only

D   InputLength                 10I 0

Internal use only

D   OutputPointer...
D                                 *

Internal use only

D   OutputLength                10I 0

Internal use only

D   Reserved                  2048A

Internal use only

D RXS_ConvertUrlPercentDS_t...
D                 DS                  Qualified Template Inz
 
D   ReturnedErrorInfo...
D                                     LikeDS(RXS_ReturnedErrorInfoDS_t) Inz
 
D   DataStructureType...
D                                5I 0 Inz(RXS_DS_TYPE_CONVERTURLPERCENT)

Internal use only

D   OnErrorMessageType...
D                                5I 0
 
D   EncodeDecode                  N

Set to RXS_ENCODE or RXS_DECODE.

Valid Values:

  • RXS_ENCODE
  • RXS_DECODE

Default Value: RXS_DECODE

D   AsciiEbcdic                   N

Determines whether the returned encoded hexadecimal values are returned as ASCII bytes (RXS_ASCII) or converted to EBCDIC (RXS_EBCDIC).

Valid Values:

  • RXS_ASCII
  • RXS_EBCDIC

Default Value: RXS_ASCII

D   InputPointer...
D                                 *

Internal use only

D   InputLength                 10I 0

Internal use only

D   OutputPointer...
D                                 *

Internal use only

D   OutputLength                10I 0

Internal use only

D   Reserved                  2050A

Internal use only

D RXS_ConvertUserDefinedDS_t...
D                 DS                  Qualified Template Inz
 
D   ReturnedErrorInfo...
D                                     LikeDS(RXS_ReturnedErrorInfoDS_t) Inz
 
D   DataStructureType...
D                                5I 0 Inz(RXS_DS_TYPE_CONVERTUSERDEFINED)

Internal use only

D   OnErrorMessageType...
D                                5I 0
 
D   From                        32A   Varying Dim(50)
 
D   To                          32A   Varying Dim(50)
 
D   InputPointer...
D                                 *

Internal use only

D   InputLength                 10I 0

Internal use only

D   OutputPointer...
D                                 *

Internal use only

D   OutputLength                10I 0

Internal use only

D   Reserved                  2048A

Internal use only

D RXS_ConvertXMLEntitiesDS_t...
D                 DS                  Qualified Template Inz
 
D   ReturnedErrorInfo...
D                                     LikeDS(RXS_ReturnedErrorInfoDS_t) Inz
 
D   DataStructureType...
D                                5I 0 Inz(RXS_DS_TYPE_CONVERTXMLENTITIES)

Internal use only

D   OnErrorMessageType...
D                                5I 0
 
D   EncodeDecode                  N

Set to RXS_ENCODE or RXS_DECODE.

Valid Values:

  • RXS_ENCODE
  • RXS_DECODE

Default Value: RXS_DECODE

D   InputPointer...
D                                 *

Internal use only

D   InputLength                 10I 0

Internal use only

D   OutputPointer...
D                                 *

Internal use only

D   OutputLength                10I 0

Internal use only

D   Reserved                  2049A

Internal use only