From YiPs Wiki (i powered)

XMLSERVICE: XMLSERVICE Samples

(click to open)

Quick Page Table of Contents

Scanning…

XMLSERVICE Advanced Topics

Goto Main Page
Goto Documents

XMLSERVICE Call CMD

CMD- RTVJOBA, RTVSYSVAL, etc.

Input:
<?xml version='1.0'?>
<script>
<cmd exec='rexx'>RTVJOBA USRLIBL(?) SYSLIBL(?)</cmd>
<cmd exec='rexx'>RTVJOBA CCSID(?N) OUTQ(?)</cmd>
<cmd exec='rexx'>RTVSYSVAL SYSVAL(QDATETIME) RTNVAR(?)</cmd>
</script>

Output:
<?xml version='1.0'?>
<script>
<cmd exec='rexx'>+++ success RTVJOBA USRLIBL(?) SYSLIBL(?)
<row>
<data desc='USRLIBL'>
QGPL       QTEMP      QDEVELOP   QBLDSYS    QBLDSYSR</data>
</row>
<row>
<data desc='SYSLIBL'>
QSYS       QSYS2      QHLPSYS    QUSRSYS</data>
</row>
</cmd>
<cmd exec='rexx'>+++ success RTVJOBA CCSID(?N) OUTQ(?)
<row>
<data desc='CCSID'>
65535</data>
</row>
<row>
<data desc='OUTQ'>
*DEV</data>
</row>
</cmd>
<cmd exec='rexx'>+++ success RTVSYSVAL SYSVAL(QDATETIME) RTNVAR(?)
<row>
<data desc='RTNVAR'>
20110919162107200560</data>
</row>
</cmd>
</script>

Note:
(?) - means output exepected here
(?N) - means output is numeric (packed, etc.). However, commands 
       featuring RTNVAR should not require cast (?N).

CMD- RTVDTAARA *CHAR *DEC

RTVDTAARA CHAR:
Input:
<?xml version='1.0'?>
<script>
<cmd>CRTDTAARA DTAARA(XMLSERVICE/DA1) TYPE(*CHAR) LEN(3) VALUE(ABC)</cmd>
<cmd exec='rexx'>RTVDTAARA DTAARA(XMLSERVICE/DA1) RTNVAR(?)</cmd>
<cmd exec='rexx'>RTVDTAARA DTAARA(XMLSERVICE/DA1 (2 1)) RTNVAR(?)</cmd>
</script>


Output:
<?xml version='1.0'?>
<script>
<cmd>+++ success CRTDTAARA DTAARA(XMLSERVICE/DA1) TYPE(*CHAR) LEN(3)</cmd>
<cmd exec='rexx'>+++ success RTVDTAARA DTAARA(XMLSERVICE/DA1) RTNVAR(?)
<row>
<data desc='RTNVAR'>
ABC</data>
</row>
</cmd>
<cmd exec='rexx'>+++ success RTVDTAARA DTAARA(XMLSERVICE/DA1 (2 1)) RTNVAR(?)
<row>
<data desc='RTNVAR'>
B</data>
</row>
</cmd>
</script>

RTVDTAARA DEC:
Input:
<?xml version='1.0'?>
<script>
<cmd>CRTDTAARA DTAARA(XMLSERVICE/DA2) TYPE(*DEC) LEN(5 2) VALUE(12.39)</cmd>
<cmd exec='rexx'>RTVDTAARA DTAARA(XMLSERVICE/DA2) RTNVAR(?)</cmd>
</script>


Output:
<?xml version='1.0'?>
<script>
<cmd>+++ success CRTDTAARA DTAARA(XMLSERVICE/DA2) TYPE(*DEC) LEN(5 2)</cmd>
<cmd exec='rexx'>+++ success RTVDTAARA DTAARA(XMLSERVICE/DA2) RTNVAR(?)
<row>
<data desc='RTNVAR'>
12.39</data>
</row>
</cmd>
</script>

XMLSERVICE Call DB2

SQL - query, prepare/execute, fetch

The following example shows a typical sequence of scripts (3 calls to XMLSERVICE).

Do your sql work in the same XML script calling your PGM/SRVPGM. Works well with QTEMP (yahoo).

Note: DB2 SQL XML does not work in-line stateless ($ctl=‘*here’), but works fine with normal private connections (ipc=‘/tmp/fred’, $ctl=‘*sbmjob’).

script 1 (create schema and table):
<?xml version='1.0'?>
<script>
<sql>
<query error='off'>create schema XMLSERVTST</query>
</sql>
<cmd>CHGLIBL LIBL(XMLSERVTST QTEMP) CURLIB(XMLSERVTST)</cmd>
<query error='off'>drop table animal</query>
<query>
create table animal(
 id integer, breed varchar(32), name char(16),
 weight decimal(7,2), height numeric(9,2))
</query>
</script>

script 2 (prepare/execute(s) insert data):
<?xml version='1.0'?>
<script>
<sql>
<prepare>
insert into 
animal (id, breed, name, weight, height) 
values (?,?,?,?,?)
</prepare>
<execute>
<parm io='in'>1</parm>
<parm io='in'>frog</parm>
<parm io='in'>hops</parm>
<parm io='in'>2.13</parm>
<parm io='in'>1.23</parm>
</execute>
<execute>
<parm io='in'>2</parm>
<parm io='in'>cat</parm>
<parm io='in'>kitty</parm>
<parm io='in'>12.13</parm>
<parm io='in'>21.23</parm>
</execute>
</sql>
<script>

script 3 (query/select/fetch all rows):
<?xml version='1.0'?>
<script>
<sql>
<query>select * from animal</query>
<describe desc='col'/>
<fetch block='all' desc='on'/>
</sql>
<script>

XMLSERVICE Call PGM/SRVPGM examples (XML/RPG)

The following examples are intended to give you working knowledge of capabilities in XMLSERVICE job(s). Only XML input (xmlin) and output (xmlout) are demostrated, so these examples do not include transport layers of XMLSERVICE (stored procedure, http, Zend Toolkit, etc.), only the relavent XML parts.

PGM array DS parameter

Example calling a typical RPG PGM with a data structure array. In this case all the parameters are io=‘both’ (input/output), so the XML going in looks exactly like the XML coming out of XMLSERVICE, except the return XML data values will have multiple records (array).

Please note that parameter data types being passed are packed decimal(12p2) and datfmt(*iso) within data structures, not just character (64a). XMLSERVICE also handles varying=‘on’.

     D job_t           ds                  qualified based(Template)
     D  dsMyHire                       D   datfmt(*iso)
     D  dsMyLeav                       D   datfmt(*iso)
     D  dsMyJob                      64A   varying
     D  dsMyPay                      12p 2

     D MyDsArray       ds                  likeds(job_t) dim(3)

      *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
      * main(): Control flow
      *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     C     *Entry        PLIST                   
     C                   PARM                    MyDsArray


XMLSERVICE Input
<?xml version='1.0'?>
<script>
<pgm name='ZZVLAD' lib='xyzlibxmlservicexyz'>
 <parm  io='both'>
   <ds dim='3' var='job_t'>
    <data type='10a' var='begin'>na</data>
    <data type='10a' var='end'>na</data>
    <data type='64a' varying='on' var='job'>na</data>
    <data type='12p2' var='salary'>0.0</data>
   </ds>
 </parm>
 <return>
  <data type='10i0'>0</data>
 </return>
</pgm>
</script>

XMLSERVICE Output:

<?xml version='1.0'?>
<script>
<pgm name='ZZVLAD' lib='XMLSERVICE'>
<parm  io='both'>
<ds dim='3' var='job_t'>
<data type='10a' var='begin'>2011-05-11</data>
<data type='10a' var='end'>2011-07-12</data>
<data type='64a' varying='on' var='job'>Frog wrangler</data>
<data type='12p2' var='salary'>7.25</data>
</ds>
<ds dim='3' var='job_t'>
<data type='10a' var='begin'>2010-01-11</data>
<data type='10a' var='end'>2010-07-12</data>
<data type='64a' varying='on' var='job'>Toad wrangler</data>
<data type='12p2' var='salary'>4.29</data>
</ds>
<ds dim='3' var='job_t'>
<data type='10a' var='begin'>2009-05-11</data>
<data type='10a' var='end'>2009-07-12</data>
<data type='64a' varying='on' var='job'>Lizard wrangler</data>
<data type='12p2' var='salary'>1.22</data>
</ds>
</parm>
<return>
<data type='10i0'>0</data>
</return>
</pgm>
</script>

PGM complex parameters plus DS

Example calling a typical RPG PGM with a few parameters, one of which is a data structure. In this case all the parameters are io=‘both’ (input/output), so the XML going in looks exactly like the XML coming out of XMLSERVICE, except the return XML data values will change to whatever the called function writes into the parameter variables.

Please note that parameter data types being passed are packed decimal (7p4, 12p2), both as individual parameters and within data structures, not just character (1a). In fact, XMLSERVICE essentially acts much like a mini RPG compilier lining up the correctly converted XML string data to it’s actual program call geometery, so that if you debug your called program all you see is real packed decimals in variables/memory (or zone decimal 12s2, or float 4f2/8f4, or integer 10i0/5i0, or hex binary 4000b, etc.).

     D  INCHARA        S              1a
     D  INCHARB        S              1a
     D  INDEC1         S              7p 4        
     D  INDEC2         S             12p 2
     D  INDS1          DS                  
     D   DSCHARA                      1a
     D   DSCHARB                      1a           
     D   DSDEC1                       7p 4      
     D   DSDEC2                      12p 2            
      *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
      * main(): Control flow
      *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     C     *Entry        PLIST                   
     C                   PARM                    INCHARA
     C                   PARM                    INCHARB
     C                   PARM                    INDEC1
     C                   PARM                    INDEC2
     C                   PARM                    INDS1

XMLSERVICE input/output:
------------------------
<?xml version='1.0'?>
<script>
<pgm name='ZZCALL' lib='xyzlibxmlservicexyz'>
 <parm  io='both'>
   <data type='1A' var='INCHARA'>a</data>
 </parm>
 <parm  io='both'>
   <data type='1A' var='INCHARB'>b</data>
 </parm>
 <parm  io='both'>
   <data type='7p4' var='INDEC1'>11.1111</data>
 </parm>
 <parm  io='both'>
   <data type='12p2' var='INDEC2'>222.22</data>
 </parm>
 <parm  io='both'>
  <ds>
   <data type='1A' var='INDS1.DSCHARA'>x</data>
   <data type='1A' var='INDS1.DSCHARB'>y</data>
   <data type='7p4' var='INDS1.DSDEC1'>66.6666</data>
   <data type='12p2' var='INDS1.DSDEC2'>77777.77</data>
  </ds>
 </parm>
 <return>
  <data type='10i0'>0</data>
 </return>
</pgm>
</script>

SRVPGM return complex array DS

Example calling a typical RPG SRVPGM with a few parameters, but returning a complex array of data strcutures (up to 999 records). In this case all the parameters are assumed io=‘both’ by default (input/output), so the XML going in looks exactly like the XML coming out of XMLSERVICE, except the return XML is a complex array of results (much more XML going out).

A second key feature of this example is the use of dou/enddo=‘label’, informing XMLSERVICE to avoid sending array data structures past the actual MyCount value provided by the RPG called program. This technique is common in modern RPG programs, so this bit of dou/enddo syntax was added to improve overall transport (not transport 999 records of unfilled data).

See the complete dicussion of filling arrays in the internals section below, but briefly the return data structure dim=‘999′ is completely initialized by repeating the XML values in the structure 999 times, this will allow unfilled records to return with “good XML data”. However, as mentioned previous this XML output was limited to dou/endo=‘mycount’ to avoid useless extra XML records untouched by the actual called program.

Again, please note that parameter data types being passed are packed decimal (12p2), integer (10i0) both as individual parameters and within data structures, not just character (10a, 4096a). In fact, XMLSERVICE essentially acts much like a mini RPG compilier lining up the correctly converted XML string data to it’s actual program call geometery, so that if you debug your called program all you see is real packed decimals in variables/memory (or zone decimal 12s2, or float 4f2/8f4, or integer 10i0/5i0, or hex binary 4000b, etc.).

     D ARRAYMAX        c                   const(999)
     D dcRec_t         ds                  qualified based(Template)
     D  dcMyName                     10A
     D  dcMyJob                    4096A
     D  dcMyRank                     10i 0
     D  dcMyPay                      12p 2
      *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
      * zzarray: check return array aggregate 
      *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     P zzarray         B                   export
     D zzarray         PI                  likeds(dcRec_t) dim(ARRAYMAX)
     D  myName                       10A
     D  myMax                        10i 0
     D  myCount                      10i 0

XMLSERVICE input:
------------------------
<?xml version='1.0'?>
<script>
<cmd comment='addlible'>ADDLIBLE LIB(xyzlibxmlservicexyz) POSITION(*FIRST)</cmd>
<pgm name='ZZSRV' lib='xyzlibxmlservicexyz' func='ZZARRAY'>
 <parm comment='search this name'>
  <data var='myName' type='10A'>Ranger</data>
 </parm>
 <parm comment='max allowed return'>
  <data var='myMax' type='10i0'>5</data>
 </parm>
 <parm comment='actual count returned'>
  <data var='myCount' type='10i0' enddo='mycount'>0</data>
 </parm>
 <return>
  <ds var='dcRec_t' dim='999' dou='mycount'>
    <data var='dcMyName' type='10A'>na</data>
    <data var='dcMyJob' type='4096A'>na</data>
    <data var='dcMyRank' type='10i0'>0</data>
    <data var='dcMyPay' type='12p2'>0.0</data>
  </ds>
 </return>
</pgm>
</script>

XMLSERVICE output:
------------------------
<?xml version='1.0'?>
<script>
<cmd comment='addlible'>+++ success ADDLIBLE LIB(XMLSERVICE) POSITIO</cmd>
<pgm name='ZZSRV' lib='XMLSERVICE' func='ZZARRAY'>
<parm comment='search this name'>
<data var='myName' type='10A'>Ranger</data>
</parm>
<parm comment='max allowed return'>
<data var='myMax' type='10i0'>5</data>
</parm>
<parm comment='actual count returned'>
<data var='myCount' type='10i0' enddo='mycount'>5</data>
</parm>
<return>
<ds var='dcRec_t' dim='999' dou='mycount'>
<data var='dcMyName' type='10A'>Ranger1</data>
<data var='dcMyJob' type='4096A'>Test 101</data>
<data var='dcMyRank' type='10i0'>11</data>
<data var='dcMyPay' type='12p2'>13.42</data>
</ds>
<ds var='dcRec_t' dim='999' dou='mycount'>
<data var='dcMyName' type='10A'>Ranger2</data>
<data var='dcMyJob' type='4096A'>Test 102</data>
<data var='dcMyRank' type='10i0'>12</data>
<data var='dcMyPay' type='12p2'>26.84</data>
</ds>
<ds var='dcRec_t' dim='999' dou='mycount'>
<data var='dcMyName' type='10A'>Ranger3</data>
<data var='dcMyJob' type='4096A'>Test 103</data>
<data var='dcMyRank' type='10i0'>13</data>
<data var='dcMyPay' type='12p2'>40.26</data>
</ds>
<ds var='dcRec_t' dim='999' dou='mycount'>
<data var='dcMyName' type='10A'>Ranger4</data>
<data var='dcMyJob' type='4096A'>Test 104</data>
<data var='dcMyRank' type='10i0'>14</data>
<data var='dcMyPay' type='12p2'>53.68</data>
</ds>
<ds var='dcRec_t' dim='999' dou='mycount'>
<data var='dcMyName' type='10A'>Ranger5</data>
<data var='dcMyJob' type='4096A'>Test 105</data>
<data var='dcMyRank' type='10i0'>15</data>
<data var='dcMyPay' type='12p2'>67.10</data>
</ds>
</return>
</pgm>
</script>

PGM very large OCCURS data

Many limits of other toolkit PGM/SRVPGM callers are not an issue with XMLSERVICE (up to 15MB to date), therefore “old school” RPG using occurs can often pass back all data records in one call. In the example below all occurs(200) records were returned in one call during testing (a ton of data and XML records, but it worked).

Please note the complexity of occurs(200) with nested zoned decimal array elements dim(15). XMLSERVICE initialized all the occurs(200) elements with the template data in ds var=‘vevsods’ dim=‘200′ (200 times same complex ds record with multiple array zoned decimal contained).

The example very large array/occurs of array data is fully XMLSERVICE initilization before the PGM call ( <parm>complex occurs ds</parm>). You may think this is a waste of CPU/memory effort, but actually XMLSERVICE helps complex data structures by pre-initilization, thereby avoiding common application code issues such as program exceptions and NOT ALL returned array elements filled,

On the better side of average, extra cycles used for full XMLSERVICE initialization greatly help XML parsers in PHP and RPG from dying due to bad returned XML (ie. RPG returned junk memory locations like “untouched” data structures storage can be deadly to XML parsers).

     D $vevsfi         s              1
     D $vevsrj         s              2
     D $vevsob         s              7s 0
     D $vevsve         s              5s 0
     D*Ergebnisdaten:
     D $vevsods        ds                  occurs(200)
     D $vsukz                  1      1
     D $vpos                   2      9
     D $vtxt                  10     39
     D $vkalw                 40    174  2 dim(15)
     D $vvsw                 175    309  2 dim(15)
     D $vvsk                 310    324  0 dim(15)
     d*
     D i               S             10i 0 inz(0)
     D j               S             10i 0 inz(0)
      *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
      * main(): Control flow
      *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     C     *Entry        PLIST
     c                   parm                    $vevsfi
     c                   parm                    $vevsrj
     c                   parm                    $vevsob
     c                   parm                    $vevsve
     c                   parm                    $vevsods

XMLSERVICE input:
------------------------
<?xml version='1.0'?>
<script>
<pgm name='ZZERICH' lib='xyzlibxmlservicexyz'>
 <parm  io='both'>
   <data var='vevsfi' type='1A'>a</data>
 </parm>
 <parm  io='both'>
   <data var='vevsrj' type='2A'>bb</data>
 </parm>
 <parm  io='both'>
   <data var='vevsob' type='7s0'>11</data>
 </parm>
 <parm  io='both'>
   <data var='vevsve' type='5s0'>22.0</data>
 </parm>
 <parm  io='both'>
  <ds var='vevsods' dim='200'>
   <data var='vsukz' type='1A'>x</data>
   <data var='vpos' type='8A'>y</data>
   <data var='vtxt' type='30A'>hallo</data>
   <data var='vkalw' type='9s2' dim='15'>9.2</data>
   <data var='vvsw' type='9s2' dim='15'>8.2</data>
   <data var='vvsk' type='1s0' dim='15'>1.0</data>
  </ds>
 </parm>
 <return>
  <data var='ret' type='10i0'>0</data>
 </return>
</pgm>
</script>

XMLSERVICE output:
------------------------
Was just too large to be copied into this wiki (gigantic XML document).

PGM/SRVPGM data structure nested inside data strucures

In the following example we have a modern RPG SRVPGM procedure that returns a complex array of nested data structures.

Note: Examples tested included very complex nested data structures, arrays of data structures, with the hope that this XMLSERVICE plumbing would be beyond normal scripting usage expectations.

      *****************************************************
      * return complex nested data structure
      * hire_t(JOBSMAX)
      *   bio_t          - identification
      *   apply_t        - resume
      *   test_t         - Acme test scores
      *   job_t(JOBSMAX) - array or previous jobs
      *****************************************************
     D bio_t           ds                  qualified based(Template)
     D  dsMyFirst                    32A   varying
     D  dsMyMid                      32A   varying
     D  dsMyLast                     32A   varying

     D test_t          ds                  qualified based(Template)
     D  dsMyIQ                        5i 0
     D  dsMyScore                     5i 0
     D  dsMyRank                     10i 0

     D apply_t         ds                  qualified based(Template)
     D  dsMyResu                  32767a   varying

     D job_t           ds                  qualified based(Template)
     D  dsMyHire                       D   datfmt(*iso)
     D  dsMyLeav                       D   datfmt(*iso)
     D  dsMyJob                      64A   varying
     D  dsMyPay                      12p 2

     D JOBSMAX         c                   const(3)
     D hire_t          ds                  qualified based(Template)
     D  myBio                              likeds(bio_t)
     D  myApply                            likeds(apply_t)
     D  myTest                             likeds(test_t)
     D  myJob                              likeds(job_t) dim(JOBSMAX)

     D demohire        PR                  likeds(hire_t) dim(JOBSMAX)
     D  forJob                       32A


XMLSERVICE input:
------------------------
<?xml version="1.0"?>
<script>
<cmd var='CHGLIBL'>CHGLIBL LIBL(xxlib) CURLIB(xxlib)</cmd>
<pgm name='DEMOHIRE' func='DEMOHIRE'>
 <parm var='search'>
  <data type='32A'>xxjob</data>
 </parm>
 <return>
  <ds dim='3' var='hire_t'>
   <ds var='bio_t'>
    <data type='32A' varying='on' var='first'>na</data>
    <data type='32A' varying='on' var='middle'>na</data>
    <data type='32A' varying='on' var='last'>na</data>
   </ds>
   <ds var='apply_t'>
    <data type='32767A' varying='on' var='resume'>na</data>
   </ds>
   <ds var='test_t'>
    <data type='5i0' var='IQ'>1</data>
    <data type='5i0' var='score'>1</data>
    <data type='10i0' var='rank'>1</data>
   </ds>
   <ds dim='3' var='job_t'>
    <data type='10a' var='begin'>na</data>
    <data type='10a' var='end'>na</data>
    <data type='64a' varying='on' var='job'>na</data>
    <data type='12p2' var='salary'>0.0</data>
   </ds>
 </ds>
 </return>
</pgm>
</script> 

PGM/SRVPGM date and time

XMLSERVICE supports date, time, timestamp as to/from PHP string. Not all RPG timfmt/datfmt format choices were tested, but should work as string … in theory (below worked).

//     D zzdate          PR              D
//     D  myDate                         D   datfmt(*iso)
$clob = <<<ENDPROC
<?xml version="1.0"?>
<pgm name='ZZSRV' lib='xyzlibxmlservicexyz' func='ZZDATE'>
<parm  io="both">
   <data type='10A'>2009-05-11</data>
</parm>
<return>
   <data type='10A'>nada</data>
</return>
</pgm>
ENDPROC;

//     D zztime          PR              T
//     D  myTime                         T   timfmt(*iso)
$clob = <<<ENDPROC
<?xml version="1.0"?>
<pgm name='ZZSRV' lib='xyzlibxmlservicexyz' func='ZZTIME'>
<parm  io="both">
   <data type='8A'>09.45.29</data>
</parm>
<return>
   <data type='8A'>nada</data>
</return>
</pgm>
ENDPROC;

//     D zzstamp         PR              Z
//     D  myStamp                        Z
$clob = <<<ENDPROC
<?xml version="1.0"?>
<pgm name='ZZSRV' lib='xyzlibxmlservicexyz' func='ZZSTAMP'>
<parm  io="both">
   <data type='26A'>2011-12-29-12.45.29.000000</data>
</parm>
<return>
   <data type='26A'>nada</data>
</return>
</pgm>
ENDPROC;


//     D zzdateUSA       PR              D   datfmt(*USA)
//     D  myDate                         D   datfmt(*USA)
$clob = <<<ENDPROC
<?xml version="1.0"?>
<pgm name='ZZSRV' lib='xyzlibxmlservicexyz' func='ZZDATEUSA'>
<parm  io="both">
   <data type='10A'>05/11/2009</data>
</parm>
<return>
   <data type='10A'>nada</data>
</return>
</pgm>
ENDPROC;

//     D zztimeUSA       PR              T   timfmt(*USA)
//     D  myTime                         T   timfmt(*USA)
$clob = <<<ENDPROC
<?xml version="1.0"?>
<pgm name='ZZSRV' lib='xyzlibxmlservicexyz' func='ZZTIMEUSA'>
<parm  io="both">
   <data type='8A'>09:45 AM</data>
</parm>
<return>
   <data type='8A'>nada</data>
</return>
</pgm>
ENDPROC;

advanced PGM using overlay keyword (BETA 1.2.1)

The following is a graphic of overlay on a DS. The idea of this program is to only set a few messages in a nested DS structure. In this case all records are inialized (INZ) to defaults, followed by an overlay to set 2 specified messages matching program expectations.

d MyErrorDs       ds                  template                                  
d  ErrorId                       8a                  
d  Severity                      3u 0                              
d  Description                  80a         

d MyErrorParm     ds                                               
d   NumOfErrors                  3u 0                              
d   ErrorList                         likeds(MyErrorDs) dim(20)    

c     *entry        plist                                          
c                   parm                    MyErrorParm            


Example overlay:
<pgm ... stuff ... >
<parm io='both' comment='parm 1'>     <------------- parm(1)
<ds var='MyErrorParm'>                <------------- beg-outmost-ds
<data type='3u0' var='NumOfErrors'/>  <------------- INZ(0) no messages
<ds var='ErrorList' dim=20 '>         <------------- INZ(stuff) dim(20) 
<data type='8a' var='ErrorId'/>       <-------------    INZ(*BLANKS)
<data type='3u0' var='Severity'/>     <-------------    INZ(0)
<data type='80a' var='Description'/>  <-------------    INZ(*BLANKS)
</ds>                                 <------------- end-of-nested-ds-dim(20)
</ds>                                 <------------- end-outmost-ds
</parm>                               <------------- end-of-parm(1)
<overlay io='both' comment='set any'> <------------- relative to parm(1)
<ds var='MyErrorParm'>                <------------- beg-outmost-ds

<data type='3u0' var='NumOfErrors'>2</data> <------- 2 messages expected

<ds var='MyErrorDs' comment='first data'>  <-------- beg-MyErrorDs(1)
<data type='8a' var='ErrorId'>12345678</data>
<data type='3u0' var='Severity'>1</data>
<data type='80a' var='Description'>Toad wrangler</data>
</ds>                                 <------------- end-MyErrorDs(1)

<ds var='MyErrorDs' comment='right behind first'> <- beg-MyErrorDs(2)
<data type='8a' var='ErrorId'>87654321</data>
<data type='3u0' var='Severity'>3</data>
<data type='80a' var='Description'>Frog wrangler</data>
</ds>                                 <------------- end-MyErrorDs(2)

</ds>                                 <------------- end-outmost-ds
</overlay>
</pgm>

advanced PGM compare RPG to XML passing array records (1.2.1)

Input to the following PGM is a simple data structure array (DS dim(20)). By design convention this program’s caller sends only a few “error records” to the PGM and this program “detects” end of “good data” via unset/blank error records (ErrorId=*BLANKS).

Technically speaking, common RPG technique aside, this PGM is living on relatively poorly designed “thin ice” because it relies on “the caller” to send at least one “uncorrupted” termination error record (ErrorId=*BLANKS) following any “good” data records. To wit, while RPG-2-RPG will “mostly work” due to the friendly RPG compiler setting char fields *BLANKS, etc., many other compliers like ILE C may pass uninitialized random junk off the stack and this RPG PGM may die with an exception.

In the case of XMLSERVICE you will see that YOU are the XML compiler (RPG compiler), so you will have to manually send a well formed XML termination record (ErrorId=*BLANKS) to stop this PGM loop below (examples follow RPG).

     H AlwNull(*UsrCtl)
     D i               s             10i 0 inz(0)
     d MyErrorDs       ds                  qualified based(Template)
     d  ErrorId                       8a
     d  Severity                      3u 0
     d  Description                  80a
     d ErrorParm       ds                  likeds(MyErrorDs) dim(20)
      *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
      * main(): Control flow
      *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     C     *Entry        PLIST                   
     C                   PARM                    ErrorParm
      /free
        for i = 1 to 20;
          // data values
          if ErrorParm(i).ErrorId = *BLANKS;
            return;
          endif;

RPG client (caller):

In the case of RPG callers, most likely RPG compiler will hide all “sins” of this program design by automatically filling in the calling structure with *BLANKS (also 0 for 3u0).

d ErrorParm ds likeds(MyErrorDs) dim(20) <--initialized by RPG compiler
ErrorParm(1).ErrorId='12345678'; // manual record
ErrorParm(2).ErrorId='12345679'; // manual record
ErrorParm(3).ErrorId=*BLANKS; // manual record termination (or missing RPG compiler default)
:
callerror(ErrorParm); // works by accident

XMLSERVICE caller:

In the case of XMLSERVICE, XML users will have to provide the termination *BLANKS record because using XML client XMLSERVICE records/nodes you are the compiler (manual XML compiler). However, many XML syntax choices are available XMLSERVICE (1.2.1), here two common:

A) <parm> send only 2 records + manually include termination record

<parm io='in'>
<ds comment='record 1'>
<data type='8a'>12345678</data>
<data type='3u0'>1</data>
<data type='80a'>danger Will Robyson</data>
</ds>
<ds comment='record 2'>
<data type='8a'>12345679</data>
<data type='3u0'>2</data>
<data type='80a'>i concur says Spook</data>
</ds>
<ds comment='termination loop blank record'>
<data type='8a'  comment='blanks'/>
<data type='3u0'  comment='0'/>
<data type='80a'  comment='blanks'/>
</ds>
</parm>

B) <parm> init all 20 records + <overlay> send 2 records

<parm io='in'>
<ds dim='20' comment='all records blank'>
<data type='8a'  comment='blanks'/>
<data type='3u0'  comment='0'/>
<data type='80a'  comment='blanks'/>
</ds>
</parm>
<overlay io='in' comment='set 2 records'>
<ds comment='record 1'>
<data type='8a'>12345678</data>
<data type='3u0'>1</data>
<data type='80a'>danger Will Robyson</data>
</ds>
<ds comment='record 2'>
<data type='8a'>12345679</data>
<data type='3u0'>2</data>
<data type='80a'>i concur says Spook</data>
</ds>
</overlay>

advanced PGM setting fewer than max XML records (1.2.1 beyond)

Example calling a typical RPG PGM with a data structure array. In this case only a few of the records will be set and the RPG program makes sure that only NumOfErrors handles the 2 out of 20 possible records. This is a common RPG technique and matching XML input below.

     d MyErrorDs       ds                  qualified based(Template)
     d  ErrorId                       8a
     d  Severity                      3u 0
     d  Description                  80a
     d ErrorParm       ds                  likeds(MyErrorDs) dim(20)
      *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
      * main(): Control flow
      *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     C     *Entry        PLIST                   
     C                   PARM                    ErrorParm
     C                   PARM                    NumOfErrors       2 0


XML input (setting only a few records):
<?xml version='1.0'?>
<script>
<pgm name='ZZVLAD2' lib='xyzlibxmlservicexyz'>
<parm io='both' comment='pointer arg 1'>
<ds var='MyErrorDs' comment='first data'>
<data type='8a' var='ErrorId'>12345678</data>
<data type='3u0' var='Severity'>1</data>
<data type='80a' var='Description'>Toad wrangler</data>
</ds>
<ds var='MyErrorDs' comment='right behind first'>
<data type='8a' var='ErrorId'>87654321</data>
<data type='3u0' var='Severity'>3</data>
<data type='80a' var='Description'>Frog wrangler</data>
</ds>
</parm>
<parm io='in' comment='pointer arg 2'>
<data type='2p0' var='NumOfErrors'>2.0</data>
</parm>
</pgm>
</script>

advanced SRVPGM/PGM customize/subset XML input/ouput with overlay (1.2.1 beyond)

At times the XMLSERVICE default input/output of any given call is just not what the client program wants to see set/get or input/output, so the overlay keyword was added to allow control over the XML.

In the following example a PGM has a bunch of very large parameters, but the client only wanted to return a subset of full data in the big parameters. Therefore, input XML large paramters were marked io=‘in’ (input only) and they will not be returned in output XML, next the overlay keyword was used with io=‘out’ to allow a custom subset XML return.

Three different uses of overlay demostrated:

     D zzbig           PR            10I 0
     D  myNam1                    32000A
     D  myNam2                    32000A
     D  myNam3                    32000A
     D  myNam4                    32000A
     D  myNam5                    32000A
     D  myNam6                    32000A
     D  myNam7                    32000A
     D  myNam8                    32000A
     D  myNam9                    32000A
      *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
      * zzbig: check big 
      *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     P zzbig           B                   export
     D zzbig           PI            10I 0
     D  myNam1                    32000A
     D  myNam2                    32000A
     D  myNam3                    32000A
     D  myNam4                    32000A
     D  myNam5                    32000A
     D  myNam6                    32000A
     D  myNam7                    32000A
     D  myNam8                    32000A
     D  myNam9                    32000A

XML input:
<?xml version='1.0'?>
<script>
<pgm name='ZZSRV' lib='xyzlibxmlservicexyz' func='ZZBIG'>
 <parm io='in'>
  <data var='myNam1' type='32000A'>Ranger1</data>
 </parm>
 <parm io='in'>
  <data var='myNam2' type='32000A'>Ranger2</data>
 </parm>
 <parm io='in'>
  <data var='myNam3' type='32000A'>Ranger3</data>
 </parm>
 <parm io='in'>
  <data var='myNam4' type='32000A'>Ranger4</data>
 </parm>

 <parm io='in'>
  <data var='myNam5' type='32000A'>Ranger5</data>
 </parm>
 <overlay io='out' offset='0' comment='prev parm'>
   <data var='myOver5' type='10A'>R5</data>
 </overlay>

 <parm io='in'>
  <data var='myNam6' type='32000A'>Ranger6</data>
 </parm>
 <parm io='in'>
  <data var='myNam7' type='32000A'>Ranger7</data>
 </parm>
 <parm io='in'>
  <data var='myNam8' type='32000A'>Ranger8</data>
 </parm>
 <parm io='in'>
  <data var='myNam9' type='32000A'>Ranger9</data>
 </parm>

 <overlay io='out' offset='0' top='on' comment='top parm'>
   <data var='myOver1' type='10A'>R1</data>
 </overlay>

 <overlay io='out' offset='192000' top='on' comment='middle parms'>
   <data var='myOverx' type='10A'>R1</data>
 </overlay>

</pgm>
</script>

advanced PGM setting fewer than max XML records using overlay (1.2.1 beyond)

Another version of setting two few records relies on the RPG program detecting unset records. As you can see in the example below, XML first initializes all the records to defaults (dim=‘20′), then only the actual working error records are used (see overlay).

Also note the output is customized by use of io=‘in’ for XML initailized so these will not appear in the XML output (dim=‘20′ input only). However, overlay is io=‘both’ so these records will both be input and output in the XML. The top=‘on’ attribute tells overlay processing that all offset=‘n’ will be calculated from the top of the first parameter (%addr(ErrorParm(1))).

     d MyErrorDs       ds                  qualified based(Template)
     d  ErrorId                       8a
     d  Severity                      3u 0
     d  Description                  80a
     d ErrorParm       ds                  likeds(MyErrorDs) dim(20)
      *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
      * main(): Control flow
      *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     C     *Entry        PLIST                   
     C                   PARM                    ErrorParm

XMLInput:
<?xml version='1.0'?>
<script>
<pgm name='ZZVLAD3' lib='xyzlibxmlservicexyz'>
<parm io='in' dim='20' comment='init all'>
<ds var='MyErrorDs' comment='first data'>
<data type='8a' var='ErrorId'/>
<data type='3u0' var='Severity'/>
<data type='80a' var='Description'/>
</ds>
</parm>
<overlay io='both' top='on' comment='set any number messages'>
<ds var='MyErrorDs' comment='first data'>
<data type='8a' var='ErrorId'>12345678</data>
<data type='3u0' var='Severity'>1</data>
<data type='80a' var='Description'>Toad wrangler</data>
</ds>
<ds var='MyErrorDs' comment='right behind first'>
<data type='8a' var='ErrorId'>87654321</data>
<data type='3u0' var='Severity'>3</data>
<data type='80a' var='Description'>Frog wrangler</data>
</ds>
</overlay>
</pgm>
</script>

advanced PGM using overlay top=‘n’ for a specific parm (1.2.2)

The following example allows for absolute top=‘n’, where ‘n’ is the number of the parm to overlay. All offset=‘n’ for the overlay will be relative from parm ‘n’. This feature will give XML the ability to “hop about” parameters to create custom input/output modeling.

Output:
myOver6 = 6666666666
myOver9 = 9999999999
myOver4 = 4444444444
myOver3 = 3333333333
myOver2 = 2222222222
myOver8 = 8888888888
myOver7 = 7777777777
myOver5 = 5555555555
myOver1 = 1111111111

Input:
//     D zzbig           PR            10I 0
//     D  myNam1                    32000A
//     D  myNam2                    32000A
//     D  myNam3                    32000A
//     D  myNam4                    32000A
//     D  myNam5                    32000A
//     D  myNam6                    32000A
//     D  myNam7                    32000A
//     D  myNam8                    32000A
//     D  myNam9                    32000A
//      *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//      * zzbig: check big 
//      *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//     P zzbig           B                   export
//     D zzbig           PI            10I 0
//     D  myNam1                    32000A
//     D  myNam2                    32000A
//     D  myNam3                    32000A
//     D  myNam4                    32000A
//     D  myNam5                    32000A
//     D  myNam6                    32000A
//     D  myNam7                    32000A
//     D  myNam8                    32000A
//     D  myNam9                    32000A
<?xml version='1.0'?>
<script>
<pgm name='ZZSRV' lib='xyzlibxmlservicexyz' func='ZZBIG'>
 <parm io='in'>
  <data var='myNam1' type='32000A'>Ranger1</data>
 </parm>
 <parm io='in'>
  <data var='myNam2' type='32000A'>Ranger2</data>
 </parm>
 <parm io='in'>
  <data var='myNam3' type='32000A'>Ranger3</data>
 </parm>
 <parm io='in'>
  <data var='myNam4' type='32000A'>Ranger4</data>
 </parm>
 <parm io='in'>
  <data var='myNam5' type='32000A'>Ranger5</data>
 </parm>
 <parm io='in'>
  <data var='myNam6' type='32000A'>Ranger6</data>
 </parm>
 <parm io='in'>
  <data var='myNam7' type='32000A'>Ranger7</data>
 </parm>
 <parm io='in'>
  <data var='myNam8' type='32000A'>Ranger8</data>
 </parm>
 <overlay io='out' offset='0' top='6' comment='parm'>
   <data var='myOver6' type='10A'>R1</data>
 </overlay>
 <parm io='in'>
  <data var='myNam9' type='32000A'>Ranger9</data>
 </parm>
 <overlay io='out' offset='0' top='9' comment='parm'>
   <data var='myOver9' type='10A'>R1</data>
 </overlay>
 <overlay io='out' offset='0' top='4' comment='parm'>
   <data var='myOver4' type='10A'>R1</data>
 </overlay>
 <overlay io='out' offset='0' top='3' comment='parm'>
   <data var='myOver3' type='10A'>R1</data>
 </overlay>
 <overlay io='out' offset='0' top='2' comment='parm'>
   <data var='myOver2' type='10A'>R1</data>
 </overlay>
 <overlay io='out' offset='0' top='8' comment='parm'>
   <data var='myOver8' type='10A'>R1</data>
 </overlay>
 <overlay io='out' offset='0' top='7' comment='parm'>
   <data var='myOver7' type='10A'>R1</data>
 </overlay>
 <overlay io='out' offset='0' top='5' comment='parm'>
   <data var='myOver5' type='10A'>R1</data>
 </overlay>
 <overlay io='out' offset='0' top='1' comment='parm'>
   <data var='myOver1' type='10A'>R1</data>
 </overlay>
</pgm>
</script>

Advanced PGM/SRVPGM binary (type=‘40b’)

Binary is a more difficult concept passing data between PHP and RPG. XMLSERVICE type=‘1024b’ is actually a HEX string representation of “binary” data passed by client/PHP side before calling XMLSERVICE ( example: $hexData = strtoupper(bin2hex(BINARYDATA)) ). XMLSERVICE converts any type=‘nnnb’ binary marked ILE call data back into HEX string representation returned back to PHP.

The length of type=‘nb’ binary is strlen(HEX)/2, because HEX specifies both the high and low character byte of the binary data:

  string = 'F0F1F2CDEF'; // is type='5b'
  string = 'F0F1';       // is type='2b'

Using HEX string representation affords XMLSERVICE great flexibility in transports, because XML is ‘just a big string’ to/from IBM i. HEX string representation ASCII/EBCDIC character conversion during transport to/from IBM i should not matter (CLOB), because both sides can understand how to make binary-to/from-string data, before ILE program is called, and/or returned to PHP (below).

Note: Using PHP with special XML considerations such as double byte you may need to use mb_convert_encoding in addition to bin2hex, pack.

<?php
require_once("myXMLSERVICEWrapper.php");

// read input PDF from file system 
$hexChar = test_get_file_hex("my.pdf");
// to/from IBM i XML transport (ibm_db2, odbc, cgi, etc.)
$returnHexChar = myXMLSERVICEWrapper(getxml($hexChar));
// write new output PDF to my file system
test_put_file_hex("mynew.pdf", $returnHexChar);

function test_get_file_hex($filename) {
  $handle = fopen($filename, "rb");
  $contents = strtoupper(bin2hex( fread( $handle, filesize($filename) ) ) );
  fclose($handle);
  return $contents;
}

function test_put_file_hex($filename, $contents) {
  file_put_contents($filename, pack( "H*", $contents ));
}

function getxml($hexChar) {
$clob1 = <<<ENDPROC1
<?xml version="1.0"?>
<script>
<pgm name='ZZSRV' lib='xyzlibxmlservicexyz' func='ZZPDF'>
 <parm comment='binary data'>
  <data var='myPDF' type='xxsizeb'>
ENDPROC1;
$clob3 = <<<ENDPROC3
  </data>
 </parm>
 <return>
  <data var='myRet' type='10i0'>0</data>
 </return>
</pgm>
</script>
ENDPROC3;
$was = array('xxsize');
$now = array(strlen($hexChar)/2);
$clob1 = str_replace($was,$now,$clob1);
$clob = $clob1;
$clob .= $hexChar;
$clob .= $clob3;
return test_lib_replace($clob);
}
?>

As seen in client/server memory (not actual pdf):
      > PHP sees ASCII $hexChar = strtoupper(bin2hex(PCFILE)); ...   
>FILE: 0x31323334 -> '31323334' or 0x3331333233333334 (memory)
      > XMLSERVICE sees EBCDIC (via CLOB) ...                             
>CLOB IN PLUGXXX -> '31323334' or 0xF3F1F3F2F3F3F3F4 (memory)
      > RPG/ILE call sees BINARY (PGM call by XMLSERVICE) ... 
>XMLSERVICE->PGM -> 0x31323334 (memory BINARY same as PC File)
      < PHP return sees $contents=XMLSERVICE(CLOB OUT, result set) ... 
<PHP: '31323334' or 0x3331333233333334 (memory)
      < new PHP BINARY file ...
FILE: 0x31323334 <- file_put_contents($filename,pack( "H*", $contents));

How does XMLSERVICE dim=‘n’ fill array initial data?

short answer … array data structure or data elements are replicated/initialized dim=‘n’ times with same matching XML values (see RPG what if below).

There is always a level of creative license with language matching (RPG-2-XML), this case we are chatting about “short hand initialization via xml”, where initialized XML data/values are replicated 3 times in job_t(3) memory acting like inz(‘value’) on each element of the data structure in the array … not possible RPG compiler qualified based(Template) shown below … but hey ok in XML.

  <ds dim='3' var='job_t'>
    <data type='10a' var='begin'>na</data>
    <data type='10a' var='end'>na</data>
    <data type='64a' varying='on' var='job'>na</data>
    <data type='12p2' var='salary'>0.0</data>
   </ds>

      * WHAT IF RPG allowed this inz() syntax (XML does above) ... 
     D job_t           ds                  qualified based(Template)
     D  dsMyHire                       D   datfmt(*iso) inz('na')
     D  dsMyLeav                       D   datfmt(*iso) inz('na')
     D  dsMyJob                      64A   varying  inz('na')
     D  dsMyPay                      12p 2 inz(0.0)

     D JOBSMAX         c                   const(3)
     D hire_t          ds                  qualified based(Template)
     D  myBio                              likeds(bio_t)
     D  myApply                            likeds(apply_t)
     D  myTest                             likeds(test_t)
     D  myJob                              likeds(job_t) dim(JOBSMAX)
      *****************************************************
      * return complex nested data structure
      *****************************************************
     P demohire        B                   export
     D demohire        PI                  dim(JOBSMAX) likeds(hire_t)
     D  forJob                       32A

<?xml version="1.0"?>
<script>
<cmd var='CHGLIBL'>CHGLIBL LIBL(xxlib) CURLIB(xxlib)</cmd>
<pgm name='DEMOHIRE' func='DEMOHIRE'>
 <parm var='search'>
  <data type='32A'>xxjob</data>
 </parm>
 <return>
  <ds dim='3' var='hire_t'>
   <ds var='bio_t'>
    <data type='32A' varying='on' var='first'>na</data>
    <data type='32A' varying='on' var='middle'>na</data>
    <data type='32A' varying='on' var='last'>na</data>
   </ds>
   <ds var='apply_t'>
    <data type='32767A' varying='on' var='resume'>na</data>
   </ds>
   <ds var='test_t'>
    <data type='5i0' var='IQ'>1</data>
    <data type='5i0' var='score'>1</data>
    <data type='10i0' var='rank'>1</data>
   </ds>
   <ds dim='3' var='job_t'>
    <data type='10a' var='begin'>na</data>
    <data type='10a' var='end'>na</data>
    <data type='64a' varying='on' var='job'>na</data>
    <data type='12p2' var='salary'>0.0</data>
   </ds>
 </ds>
 </return>
</pgm>
</script> 

Can i pass any data in system API (like data queues)?

There is no “limit” to what you pass in a data queue API value field (other than system API rules of the system) … character, packed, data structures, zoned, int, real, double, (your imagination is the limit) … however you need to get API QSNDDTAQ/QRCVDTAQ structure matching correct, lengths, etc. (just like RPG program, it is no different).

1) Matching send data queue (same or different XMLSERVICE process):
<pgm name='QSNDDTAQ'>
<parm io='in'>
<data type='10A'>MYDATAQ</data>
</parm>
<parm io='in'>
<data type='10A'>xyzlibxmlservicexyz</data>
</parm>
<parm io='in'>
<data type='5p0'>some decimal length i did not figure out by hand matching below</data>
</parm>
<parm io='in'>
  <ds dim='3' var='hire_t'>
   <ds var='bio_t'>
    <data type='32A' varying='on' var='first'>na</data>
    <data type='32A' varying='on' var='middle'>na</data>
    <data type='32A' varying='on' var='last'>na</data>
   </ds>
   <ds var='apply_t'>
    <data type='32767A' varying='on' var='resume'>na</data>
   </ds>
   <ds var='test_t'>
    <data type='5i0' var='IQ'>1</data>
    <data type='5i0' var='score'>1</data>
    <data type='10i0' var='rank'>1</data>
   </ds>
   <ds dim='3' var='job_t'>
    <data type='10a' var='begin'>na</data>
    <data type='10a' var='end'>na</data>
    <data type='64a' varying='on' var='job'>na</data>
    <data type='12p2' var='salary'>0.0</data>
   </ds>
 </ds>
</parm>
</pgm>


2) Matching receive data queue (same or different XMLSERVICE process):
<pgm name='QRCVDTAQ'>
 <parm  io='in'>
   <data type='10A'>MYDATAQ</data>
 </parm>
 <parm  io='in'>
   <data type='10A'>xyzlibxmlservicexyz</data>
 </parm>
 <parm  io='in'>
   <data type='5p0'>some decimal length i did not figure out by hand matching below</data>
 </parm>
 <parm io='out'>
  <ds dim='3' var='hire_t'>
   <ds var='bio_t'>
    <data type='32A' varying='on' var='first'>na</data>
    <data type='32A' varying='on' var='middle'>na</data>
    <data type='32A' varying='on' var='last'>na</data>
   </ds>
   <ds var='apply_t'>
    <data type='32767A' varying='on' var='resume'>na</data>
   </ds>
   <ds var='test_t'>
    <data type='5i0' var='IQ'>1</data>
    <data type='5i0' var='score'>1</data>
    <data type='10i0' var='rank'>1</data>
   </ds>
   <ds dim='3' var='job_t'>
    <data type='10a' var='begin'>na</data>
    <data type='10a' var='end'>na</data>
    <data type='64a' varying='on' var='job'>na</data>
    <data type='12p2' var='salary'>0.0</data>
   </ds>
 </ds>
 </parm>
 <parm  comment='wait' io='in'>
   <data type='5p0'>0</data>
 </parm>
</pgm>

Advanced batch XMLSERVICE (alpha version 1.5.1)

An option for those long running jobs. Release your script (ctl=‘*batch’) and check back later for the XMLSERVICE results (ctl=‘*get’). Example is PHP stub, but dmostrates the idea.

Note: *batch is alpha because the “check back” is not right yet (waits, should just return back busy).

switch($i) {
  case 0:
    echo "Submitted XMLSERVICE batch request ...\n";
    $ctl = $ctlstart . " *batch";
    $clobIn = getxml1();
    break;
  case 1:
    echo "Submitted XMLSERVICE batch request ...\n";
    $ctl = $ctlstart . " *batch";
    $clobIn = getxml2();
    break;
  case 2:
    echo "Doing something else waiting for batch ...\n";
    $ctl = $ctlstart;
    $clobIn = getxml3();
    break;
  default:
    echo "Sleeping waiting for batch ...\n";
    sleep(2);
    $ctl = $ctlstart . " *get";
    $clobIn = "<?xml version='1.0'?>";
    break;
}

// 5250:
// call qp2term
// /QOpenSys/usr/bin/system -i 'wrkactjob'
function getxml1() {
$clob = <<<ENDPROC
<?xml version='1.0'?>
<script>
<sh rows='on'>/QOpenSys/usr/bin/system -i 'wrkactjob'</sh>
</script>
ENDPROC;
return $clob;
}

// 5250:
// call qp2term
// /QOpenSys/usr/bin/ls /tmp
function getxml2() {
$clob = <<<ENDPROC
<?xml version='1.0'?>
<script>
<sh>/QOpenSys/usr/bin/ls /tmp</sh>
</script>
ENDPROC;
return $clob;
}


//     D  INCHARA        S              1a
//     D  INCHARB        S              1a
//     D  INDEC1         S              7p 4        
//     D  INDEC2         S             12p 2
//     D  INDS1          DS                  
//     D   DSCHARA                      1a
//     D   DSCHARB                      1a           
//     D   DSDEC1                       7p 4      
//     D   DSDEC2                      12p 2            
//      *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//      * main(): Control flow
//      *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//     C     *Entry        PLIST                   
//     C                   PARM                    INCHARA
//     C                   PARM                    INCHARB
//     C                   PARM                    INDEC1
//     C                   PARM                    INDEC2
//     C                   PARM                    INDS1
function getxml3() {
$clob = <<<ENDPROC
<?xml version='1.0'?>
<script>
<pgm name='ZZCALL' lib='xyzlibxmlservicexyz'>
 <parm  io='both'>
   <data type='1A' var='INCHARA'>a</data>
 </parm>
 <parm  io='both'>
   <data type='1A' var='INCHARB'>b</data>
 </parm>
 <parm  io='both'>
   <data type='7p4' var='INDEC1'>11.1111</data>
 </parm>
 <parm  io='both'>
   <data type='12p2' var='INDEC2'>222.22</data>
 </parm>
 <parm  io='both'>
  <ds>
   <data type='1A' var='INDS1.DSCHARA'>x</data>
   <data type='1A' var='INDS1.DSCHARB'>y</data>
   <data type='7p4' var='INDS1.DSDEC1'>66.6666</data>
   <data type='12p2' var='INDS1.DSDEC2'>77777.77</data>
  </ds>
 </parm>
 <return>
  <data type='10i0'>0</data>
 </return>
</pgm>
</script>
ENDPROC;
return test_lib_replace($clob);
}

Author(s)

Tony “Ranger” Cairns - IBM i PHP / PASE

Retrieved from http://youngiprofessionals.com/wiki/index.php/XMLSERVICE/XMLSERVICESamples
Page last modified on October 21, 2013, at 04:50 PM EST