Consuming an XML service with COBOL

By | February 24, 2014

Now that we can make HTTP web requests directly from our COBOL program and do this with SSL Security, we should be able to use these skills access a service that returns non-SOAP XML.  JSON is preferable these days, however we can leverage the native COBOL parsing support for XML and, as far as I know, there is no native JSON parser as yet.

I’m starting with the COBOL SSL program I posted earlier.  Much of the program is the same.  I am going to access one of the Google APIs, the Geocoding API, which takes an HTTP query string request and returns an XML document.  (Note that if you use this API in a business application, you should become a Maps for Business customer.)  It would not be too difficult to generate an XML request for some service using the COBOL XML Generate support.

Some issues I encountered in this project:

  • The Google API returns a chunked response, so multiple gsk_secure_socket_read calls are required (which I put in a perform loop).
  • Through trial and error, I decided to determine the end of the response by looking for a contiguous pair of carriage-return linefeed combinations.
           perform with test after
                   until  ws-reply (ws-reply-tail-offset : 4)
                          = ws-double-cr-lf-ascii

      *      gsk_status (*gsk_secure_socket_read) (
      *        gsk_handle              soc_handle,
      *        char *                  buffer,
      *        int                     size,
      *        int *                   length);

             compute ws-reply-length = length of ws-reply - ws-offset

             call 'gsk_secure_socket_read'
               using by value          ws-gsk-soc-handle
                     by value          address of ws-reply (ws-offset :)
                     by value          ws-reply-length
                     by value          address of ws-reply-length
               returning               ws-rc

             if ws-rc not = zero
               move z'gsk_secure_socket_read'
                                     to ws-gsk-function
               go to gsk-error

             compute ws-reply-tail-offset =
               ws-offset + ws-reply-length - 4

             add ws-reply-length to ws-offset

  • Using the XMLPARSE(XMLSS) compiler option, the XML parser expects the document to be in the host CCSID and it ignores the encoding attribute in the XML header.
  • I had to locate the start of the XML document inside of the HTTP response otherwise the XML PARSE verb generated a strange exception.
  • I identified the end of the XML document as being when the highest level group element closed as indicated by the generated indentation retuning to the base level.  Setting XML-CODE to -1 ends the parse operation.
  • The COBOL XML PARSE verb seems to treat some white-space data (blanks and newline characters) as data, so, for example,

    seems to return a value of x’154040′ for abc and “foo” for def.

      * Find beginning of document

             varying ws-offset from 1 by 1
             until   ws-reply (ws-offset : 6) = '<?xml '

      * apparently x'15' is treated as data, not white-space

           inspect ws-reply (ws-offset :)
             replacing all x'15' by ' '

           move +1 to ws-indent

           xml parse ws-reply (ws-offset :)
             processing procedure goecoderesponse-handler
             on exception
               if xml-code not = -1
                 display 'XML document error ' xml-code
                 move zero to return-code


           evaluate xml-event
             when 'START-OF-ELEMENT'
               display ws-blank (1 : ws-indent)  xml-text ':'
               compute ws-indent = ws-indent + 2
             when 'CONTENT-CHARACTERS'
               if xml-text not = spaces
                 display ws-blank (1 : ws-indent)  xml-text
             when 'END-OF-ELEMENT'
               compute ws-indent = ws-indent - 2
               if ws-indent = 1
                 move    -1  to  XML-CODE
             when 'EXCEPTION'
               display 'Exception '  xml-code
                       ' at offset ' length of xml-text '.'

Here is the complete source: cobxml.cbl. Compile as in the earlier COBSSL program.

This version does not handle chunked data very well as it assumes the returned XML will be all in one chunk, which is not always the case.

Leave a Reply

Your email address will not be published. Required fields are marked *