%HANDLER (handlingProcedure : communicationArea )

Start of change%HANDLER is used to identify a procedure to handle an event or a series of events. %HANDLER does not return a value, and it can only be specified as the first operand of XML-SAX, XML-INTO and DATA-INTO.End of change

The first operand, handlingProcedure specifies the prototype of the handling procedure. The return value and parameters specified by the prototype, or by the procedure interface if the prototype is not explicitly specified, must match the parameters required for the handling procedure; the requirements are determined by the operation that %HANDLER is specified for. See XML-SAX (Parse an XML Document), XML-INTO (Parse an XML Document into a Variable) or DATA-INTO (Parse a Document into a Variable) for the specific requirements for the definition of the handling procedures.

The second operand, communicationArea, specifies a variable to be passed as a parameter on every call to the handling procedure. The operand must be an exact match for the first prototyped parameter of the handling procedure, according to the same rules that are used for checking prototyped parameters passed by reference. The communication-area parameter can be any type, including arrays and data structures.

When an operation code uses the %HANDLER built-in function, the following sequence of events occurs:
  1. The operation using the %HANDLER built-in function begins.
  2. When an event occurs during the operation that must be handled by the handling procedure, the RPG runtime calls the handling procedure specified as the first operand of %HANDLER. The first parameter passed to the handling procedure is the communication area that was specified as the second operand of %HANDLER. The other parameters depend on the operation and the nature of the event that occurred.
  3. The handling procedure processes the parameters, possibly updating the communication-area parameter.
  4. The handling procedure returns a zero if it completed successfully, and a non-zero value if it did not complete successfully.
  5. If the returned value was zero, the RPG runtime continues processing until either the operation is complete, or another event occurs. If the returned value was not zero, the operation ends.
  6. If another event occurs, the handling procedure is called again. If the previous call to the handling procedure changed the communication area, the changes can be seen on subsequent calls.
  7. When the operation is complete, control passes to the statement following the operation that used the %HANDLER built-in function. If the handling procedure changed the communication area, the changes can be seen in the procedure that used the %HANDLER built-in function.
The communication area can be used for several purposes.
  1. To communicate information from the procedure coding the %HANDLER built-in function to the handling procedure.
  2. To communicate information from the handling procedure back to the procedure coding the %HANDLER built-in function.
  3. To keep state information between successive calls of the handling procedure. State information can also be kept in static variables in the handling procedure, but when static variables are used, incorrect results can occur if the handling procedure has been enabled by more than one %HANDLER operation. By using a communication area parameter, the usages of the handling procedure are independent from each other.
Figure 1. Using a communication-area with %HANDLER
 * Data structure used as a parameter between
 * the XML-SAX operation and the handling
 * procedure.
 *   - "attrName" is set by the procedure doing the
 *     XML-SAX operation and used by the handling procedure
 *   - "attrValue" is set by the handling procedure
 *     and used by the procedure doing the XML-SAX
 *     operation
 *   - "haveAttr" is used internally by the handling
 *     procedure
D info            DS
D   attrName                    20A    VARYING
D   haveAttr                      N
D   attrValue                   20A    VARYING

 * Prototype for procedure "myHandler" defining
 * the communication-area parameter as being
 * like data structure "info"
D myHandler       PR            10I 0
D   commArea                           LIKEDS(info)
D   event                       10I 0  VALUE
D   string                        *    VALUE
D   stringLen                   20I 0  VALUE
D   exceptionId                 10I 0  VALUE
 /free
   // The purpose of the following XML-SAX operation
   // is to obtain the value of the first "companyname"
   // attribute found in the XML document.

   // The communication area "info" is initialized with
   // the name of the attribute whose value is
   // to be obtained from the XML document.
   attrName = 'companyname';

   // Start SAX processing.  The procedure "myHandler"
   // will be called for every SAX event; the first
   // parameter will be the data structure "info".
   xml-sax(e) %handler(myHandler : info) %xml(xmldoc);
   // The XML-SAX operation is complete.  The
   // communication area can be checked to get the
   // value of the attribute.
   if not %error() and attrValue <> '';
     dsply (attrName + '=' + attrValue);
   endif;
:
:
 * The SAX handling procedure "myHandler"
P myHandler       B
D                 PI            10I 0
D   comm                               LIKEDS(info)
D   event                       10I 0  VALUE
D   string                        *    VALUE
D   stringLen                   20I 0  VALUE
D   exceptionId                 10I 0  VALUE
D value           S          65535A    VARYING
D                                      BASED(string)
D ucs2value       S          16383C    VARYING
D                                      BASED(string)
D rc              S             10I 0  INZ(0)
 /free

     select;
     // When the event is a "start document" event,
     // the handler can initialize any internal
     // subfields in the communication area.
     when event = *XML_START_DOCUMENT;
        comm.haveAttr = *OFF;

     // When the event is an "attribute name" event,
     // and the value of the event is the required
     // name, the internal subfield "haveAttr" is
     // set to *ON.  If the next event is an
     // attribute-value event, the value will be
     // saved in the "attrValue" subfield.
     when event = *XML_ATTR_NAME
     and  %subst(value : 1 : stringLen) = comm.attrName;
        comm.haveAttr = *ON;
        comm.attrValue = '';

     // When "haveAttr" is on, the data from any
     // attribute-value should be saved in the "attrValue"
     // string until the *XML_END_ATTR event occurs
     when comm.haveAttr;
        select;
        when event = *XML_ATTR_CHARS
        or   event = *XML_ATTR_PREDEF_REF;
           comm.attrValue +=
               %subst(value : 1 : stringLen);
        when event = *XML_ATTR_UCS2_REF;
           stringLen = stringLen / 2;
           comm.attrValue +=
               %char(%subst(ucs2value : 1 : stringLen));
        when event = *XML_END_ATTR;
           // We have the entire attribute value
           // so no further parsing is necessary.
           // A non-zero return value tells the
           // RPG runtime that the handler does
           // not want to continue the operation
           rc = -1;
       endsl;

     endsl;

   return rc;
 /end-free
P                 E

For more examples of %HANDLER, see XML-SAX (Parse an XML Document) and XML-INTO (Parse an XML Document into a Variable).

For more information, see XML Operations or Built-in Functions.