How to handle variably repeating content in COBOL

In COBOL, you cannot process variably repeating content by using pointer arithmetic to address each instance of the data. Other programming languages do not have this limitation. This example shows you how to handle variably repeating content in COBOL for a Web service application.

This technique also applies to transforming XML to application data using the TRANSFORM API commands. The following example WSDL document represents a Web service with application data that consists of an 8-character string that recurs a variable number of times:
<?xml version="1.0"?>
<definitions name="ExampleWSDL" 
             targetNamespace="http://www.example.org/variablyRepeatingData/" 
             xmlns="http://schemas.xmlsoap.org/wsdl/" 
             xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" 
             xmlns:tns="http://www.example.org/variablyRepeatingData/" 
             xmlns:xsd="http://www.w3.org/2001/XMLSchema">

 <types>
   <xsd:schema targetNamespace="http://www.example.org/variablyRepeatingData/">
     <xsd:element name="applicationData">
       <xsd:complexType>
         <xsd:sequence>
           <xsd:element name="component" minOccurs="1" maxOccurs="unbounded">
             <xsd:simpleType>
               <xsd:restriction base="xsd:string">
                 <xsd:length value="8"/>
               </xsd:restriction>
             </xsd:simpleType>
           </xsd:element>
         </xsd:sequence>
       </xsd:complexType>
     </xsd:element>
   </xsd:schema>
 </types>

 <message name="exampleMessage">
   <part element="tns:applicationData" name="messagePart"/>
 </message>

 <portType name="examplePortType">
   <operation name="exampleOperation">
     <input message="tns:exampleMessage"/>
     <output message="tns:exampleMessage"/>
   </operation>
 </portType>

 <binding name="exampleBinding" type="tns:examplePortType">
   <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
   <operation name="exampleOperation">
     <soap:operation soapAction=""/>
     <input><soap:body parts="messagePart" encodingStyle="" use="literal"/></input>
     <output><soap:body parts="messagePart" encodingStyle="" use="literal"/></output>
   </operation>
 </binding>
</definitions>
Processing this WSDL document through DFHWS2LS generates the following COBOL language structures:
           03 applicationData.
 
             06 component-num                 PIC S9(9) COMP-5 SYNC.
             06 component-cont                PIC X(16).
 
 
         01 DFHWS-component.
           03 component                     PIC X(8).
Note that the 8-character component field is defined in a separate structure called DFHWS-component. The main data structure is called applicationData and it contains two fields, component-num and component-cont. The component-num field indicates how many instances of the component data are present and the component-cont field indicates the name of a container that holds the concatenated list of component fields.
The following COBOL code demonstrates one way to process the list of variably recurring data. It makes use of a linkage section array to address subsequent instances of the data, each of which is displayed by using the DISPLAY statement:
IDENTIFICATION DIVISION.                                           
       PROGRAM-ID.    EXVARY.                                      
                                                                   
       ENVIRONMENT DIVISION.                                       
       DATA DIVISION.                                              
       WORKING-STORAGE SECTION.                                    
                                                                   
      * working storage variables                                  
       01 APP-DATA-PTR             USAGE IS POINTER.               
       01 APP-DATA-LENGTH          PIC S9(8) COMP.                 
       01 COMPONENT-PTR            USAGE IS POINTER.               
       01 COMPONENT-DATA-LENGTH    PIC S9(8) COMP.                 
       01 COMPONENT-COUNT          PIC S9(8) COMP-4 VALUE 0.       
       01 COMPONENT-LENGTH         PIC S9(8) COMP.                 
                                                                   
       LINKAGE SECTION.                                            
                                                                   
      * a large linkage section array                              
       01 BIG-ARRAY PIC X(659999).                                 
                                                                   
      * application data structures produced by DFHWS2LS           
      * this is normally referenced with a COPY statement          
       01 DFHWS2LS-data.                                           
          03 applicationData.                                      
            06 component-num  PIC S9(9) COMP-5 SYNC.               
            06 component-cont PIC X(16).                           
                                                                   
       01 DFHWS-component.                                         
          03 component        PIC X(8).                            
                                                                   
                                                                   
                                                                   
       PROCEDURE DIVISION USING DFHEIBLK.                          
       A-CONTROL SECTION.                                          
       A010-CONTROL.                                               
                                                                   
      * Get the DFHWS-DATA container                               
           EXEC CICS GET CONTAINER('DFHWS-DATA')                   
                     SET(APP-DATA-PTR)                             
                     FLENGTH(APP-DATA-LENGTH)                      
           END-EXEC                                                
           SET ADDRESS OF DFHWS2LS-data TO APP-DATA-PTR            
                                                                   
      * Get the recurring component data                           
           EXEC CICS GET CONTAINER(component-cont)                 
                     SET(COMPONENT-PTR)                            
                     FLENGTH(COMPONENT-DATA-LENGTH)                
           END-EXEC                                                
                                                                   
      * Point the component structure at the first instance of the data 
           SET ADDRESS OF DFHWS-component TO COMPONENT-PTR          
                                                                   
      * Store the length of a single component                     
           MOVE LENGTH OF DFHWS-component TO COMPONENT-LENGTH    
                                                                   
      * process each instance of component data in turn            
           PERFORM WITH TEST AFTER                                 
                 UNTIL COMPONENT-COUNT = component-num             
                                                                   
      * display the current instance of the data                   
              DISPLAY 'component value is: ' component             
                                                                   
      * address the next instance of the component data            
              SET ADDRESS OF BIG-ARRAY TO ADDRESS OF DFHWS-component 
              SET ADDRESS OF DFHWS-component 
                  TO ADDRESS OF BIG-ARRAY (COMPONENT-LENGTH + 1:1)  
              ADD 1 TO COMPONENT-COUNT                             
                                                                   
      * end the loop                                               
           END-PERFORM.                                            
                                                                   
      * Point the component structure back at the first instance of    
      * of the data, for any further processing we may want to perform 
           SET ADDRESS OF DFHWS-component TO COMPONENT-PTR             
                                                                    
      * return to CICS.                                             
                                                                    
           EXEC CICS                                                
                RETURN                                              
           END-EXEC                                                 
                                                                    
           GOBACK.                                                
The code above provides a generic solution to handling variably repeating content. The array, BIG-ARRAY, moves to the start of each component in turn and does not remain fixed at the start of the data. The component data structure is then moved to point at the first byte of the next component. COMPONENT-PTR can be used to recover the start position of the component data if required.
Here is an example SOAP message that conforms to the WSDL document:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
 <SOAP-ENV:Body>
   <applicationData xmlns="http://www.example.org/variablyRepeatingData/">
     <component xmlns="">VALUE1</component>
     <component xmlns="">VALUE2</component>
     <component xmlns="">VALUE3</component>
   </applicationData>
 </SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Here is the output produced by the COBOL program when it processes the SOAP message:
CPIH 20080115103151 component value is: VALUE1
CPIH 20080115103151 component value is: VALUE2
CPIH 20080115103151 component value is: VALUE3