This page is a lookup for %xlate: its parameters, the rule for a from list longer than to, and the case-conversion pattern it is most often used for. For the rest of the string functions, see the RPGLE String BIFs Reference. The complete list of BIFs is in the RPGLE Built-in Functions Reference.
All examples are free-form RPGLE. Positions in a string start at 1.
Syntax
%xlate(from : to : string {: start {: *natural | *stdcharsize}})
| Parameter | Meaning |
|---|---|
from | The characters to look for. Character, graphic or UCS-2 data, fixed or varying |
to | The replacement characters, in the same positions as from. Must be the same data type as from and string |
string | The string to translate |
start | Optional. The first position in string to translate. Defaults to 1 |
*natural or *stdcharsize | Optional, and must be the last parameter when given. Chooses whether start counts characters or bytes for multibyte data |
%xlate returns a value of the same type and length as string.
How the translation works
Each character of string, starting at start, is compared against from. When it matches a character in from, it is replaced by the character in the same position of to. Characters not found in from are left unchanged.
dcl-s result varchar(20);
result = %xlate('abc' : 'ABC' : 'a cat'); // 'A CAt'
Only a and c are in the from list here, so t is left alone even though it also appears in the source string.
If a character appears twice in the from list
IBM’s reference does not state a rule for a character that is duplicated in from. Run on a real IBM i 7.5 system (PUB400, 2026-10-12), %xlate('aab' : 'XYZ' : 'ab') returned 'YZ': the last occurrence of the duplicated a (position 2, mapping to Y) won over the first (position 1, mapping to X). This is the observed behavior of the %XLATE built-in function on that system and release, not a documented IBM guarantee. It should also not be confused with the separate, legacy fixed-format XLATE operation code, which is a different op with its own documentation. Because this edge case is unverified by IBM’s documentation, write from with unique characters whenever possible, so the result cannot depend on it at all.
dcl-s result varchar(10);
result = %xlate('aab' : 'XYZ' : 'ab'); // 'YZ' observed on IBM i 7.5 (PUB400): the duplicated 'a'
// resolves to its last from-position (2, 'Y'), not 'X'
If from is longer than to
When from has more characters than to, the extra characters at the end of from are ignored; they have no matching replacement and are treated as if they were not in the list at all.
dcl-s result varchar(10);
result = %xlate('abc' : 'XY' : 'abc'); // 'XYc': 'c' has no matching position in 'to' and is unchanged
to must not be longer than from; every character in to corresponds to one in from at the same position.
Case conversion
The most common use of %xlate is converting a string to all uppercase or all lowercase, giving the full alphabet as both lists.
dcl-s upper varchar(20);
dcl-s original varchar(20) inz('Smith, Anna');
upper = %xlate('abcdefghijklmnopqrstuvwxyz' :
'ABCDEFGHIJKLMNOPQRSTUVWXYZ' : original); // 'SMITH, ANNA'
Writing the full alphabet by hand is easy to get wrong; a one-character slip in either list silently maps the wrong letter. Keep the two constants together and check their lengths match, or declare them once as named constants and reuse them everywhere a case conversion is needed.
dcl-c lowerAlpha 'abcdefghijklmnopqrstuvwxyz';
dcl-c upperAlpha 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
upper = %xlate(lowerAlpha : upperAlpha : original);
Translating only part of a string
The optional start parameter limits translation to the characters from that position onward; characters before start are copied through unchanged.
dcl-s result varchar(20);
result = %xlate('abc' : 'ABC' : 'abcabc' : 4); // 'abcABC', the first three characters untouched
%XLATE compared with %SCANRPL and %TRIM
%xlate replaces individual characters one for one, wherever they occur. It does not look for a substring and does not change the length of the result. %scanrpl replaces whole substrings and can change length. %trim removes characters from the edges rather than translating them in place.
| BIF | Operates on | Changes length? |
|---|---|---|
%xlate | Individual characters, anywhere in the string | No |
%scanrpl | A whole substring, wherever it is found | Yes |
%trim, %triml, %trimr | Characters at one or both edges only | Yes |
Common mistakes
- Supplying
fromandtolists of different data types, which the compiler rejects. - Miscounting characters when writing out a full alphabet by hand for case conversion, which silently maps the wrong letter instead of failing to compile.
- Expecting
%xlateto find and replace a substring. It replaces single characters only; use%scanrplfor substring replacement. - Making
tolonger thanfrom. The extra characters intohave no effect because every position intomust correspond to a character infrom. - Forgetting that a character not listed in
frompasses through unchanged rather than being removed.
FAQ
How do I convert a string to uppercase in RPGLE?
Use %xlate with the lowercase alphabet as from and the uppercase alphabet as to: %xlate('abc...z' : 'ABC...Z' : string).
What happens to a character in the string that is not in the from list?
It is left unchanged. %xlate only replaces characters that appear in from; everything else passes through.
Can %XLATE replace a whole word or substring?
No. It translates one character at a time. To replace a substring, use %scanrpl from the RPGLE %SCAN and %SCANRPL Reference.
Related BIFs
- RPGLE String BIFs Reference: the full string family, including
%checkand%trim. - RPGLE %SCAN and %SCANRPL Reference: substring search and replacement.
- RPGLE Built-in Functions Reference: the full index by task.
Summary
%xlate(from : to : string)replaces each character ofstringthat appears infromwith the character in the matching position ofto.- A duplicate character in
fromwas observed resolving to its last occurrence on IBM i 7.5 (PUB400); this is not documented by IBM, so writefromwith unique characters instead of relying on it. Extra characters at the end offromwith no match intoare ignored. - The usual use is case conversion with the full alphabet as both lists; a substring replacement needs
%scanrplinstead.