XML Syntax Extensions

This describes the XML syntax extensions provided to enable COBOL programs to input and output XML.

In this Chapter

Overview

Yopur COBOL development system supports the creation of relationships between COBOL data structures and element definitions in XML schemas. You can create COBOL XML syntax extensions, which enable you to code references to XML structures right into your COBOL definitions. These XML structures are used to input and output information in an XML format.

Syntax for Handling XML in COBOL

Syntax is provided specially designed to XML-enable COBOL. The following paragraph and clause descriptions are specifically for reading and writing XML from COBOL.

Note: If you want to compile the examples in this section, be sure to place the line numbers starting in column 3.

SELECT Paragraph

The SELECT paragraph has been extended to enable you to assign a file name to an XML stream using the ASSIGN clause. The ASSIGN clause determines the routing of the XML stream and declares the schema that the stream conforms to. The actual format of the stream is solely determined by the record definitions contained in the XML Descriptor (XD) paragraph in the File Section.

XML Syntax - SELECT Clause

XML Description Paragraph (XD)

For every file with an organization of XML, a set of record definitions is required to define the format of the XML stream being manipulated. These record definitions are contained in the XD paragraph in the File Section of the source program.

The following are not supported in the XD paragraph:

XML Syntax - XD File Description

IDENTIFIED BY and IS ATTRIBUTE Clauses

Use this syntax when declaring a COBOL data record to map the record to an XML element (tag) or an XML attribute that is defined in an XML schema or document.

You match up an XML tag with a COBOL data record using IDENTIFIED BY, and match up attributes for the XML tags with the addition of IS ATTRIBUTE. For example:

If you had an XML document that contained the following:

<company_name type="accounting">Webber Lynch</company_name>

a matching COBOL record using the IDENTIFIED BY and IS ATTRIBUTE clauses would be as follows:

    05  company identified by "company_name".
        10  company-name-value   pic X(30).
        10  company-type    pic x(10) 
            identified by "type" is attribute.

XML Syntax - IDENTIFIED BY Clause

You can work with variable tag and attribute names in your XML-enabled program, as well as known tag names. Using this method, you specify tags and attributes by substituting a COBOL data-name for a tag or an attribute name. On an XML file opened for output, this allows you to write purely dynamic and arbitrarily complex XML documents. On a file opened for input this allows you to read such complex documents. For example, the following program reads any XML stream that has a single root tag, any number of single nested tags and any number of attributes per tag:

Example 1: Using the IDENTIFIED BY and IS ATTRIBUTE clauses

0010 $set preprocess(prexml) o(foo.pp) warn endp
0030
0040 select doc           assign address of mybuf
0050                      organization is xml 
0060                      document-type is external doc-type
0070                      file status is doc-status.
0080 xd doc.
0090 01  root-tag            identified by root-tag-name.
0100     10  root-tag-name   pic x(80).
0110     10  root-tag-val    pic x(80).
0120     10  root-tag-attr   identified by root-tag-attr-name 
0130                         is attribute.
0140         15  root-tag-attr-name pic x(80).
0150         15  root-tag-attr-val  pic x(80).
0160
0170     10  sub-tag              identified by sub-tag-name.
0180         15  sub-tag-name pic x(80).
0190         15  sub-tag-val  pic x(80).
0200         15  sub-tag-attr identified by sub-tag-attr-name 
0210                          is attribute.
0220             20  sub-tag-attr-val  pic x(80).
0230             20  sub-tag-attr-name pic x(80).
0240
0250 working-storage section.
0260 01  doc-type            pic x(80).
0270 01  doc-status          pic s9(9) comp.
0280 01  mybuf.
0290     10  pic x(300) value
0300     '<library location="here" '
0310     &    'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" '
0320     &    'xsi:schemaLocation="library.xsd">'
0330     &  '<book published="yes" goodreading="ok">'
0340     &   'booktext'
0350     &  '</book>'
0360     &  'is a place'
0370     & '</library>'.
0380
0390 procedure division.
0400     open input doc
0410     read doc
0420     display "Document type is: " doc-type
0430     display "Tag name: " root-tag-name
0440     display "Tag value:" root-tag-val
0450     start doc key root-tag-attr
0460     *> 
0470     *> Loop through all attributes dumping names 
0480     *>
0490
0500     perform until exit
0510        read doc next key root-tag-attr
0520        if  doc-status not = 0
0530            exit perform
0540        end-if
0550        display "Attribute name : " root-tag-attr-name
0560        display "Attribute value: " root-tag-attr-val
0570     end-perform
0580
0590     *> Loop through all sub-tags
0600     start doc key sub-tag
0610     perform until exit
0620        read doc  
0630          next key sub-tag *> index is 1 is default
0640        if  doc-status not = 0
0650            exit perform
0660        end-if
0670        display " Sub tag name: " sub-tag-name
0680        display " Sub tag value:" sub-tag-val 
0690
0700        start doc key sub-tag-attr index is 1
0710        perform until exit
0720            read doc next key sub-tag-attr
0730            if  doc-status not = 0
0740                exit perform
0750            end-if
0760            display " Sub tag attribute name : "
0770              sub-tag-attr-name
0780            display " Sub tag attribute value: " 
0790              sub-tag-attr-val
0800        end-perform
0810    end-perform
0820
0830    close doc
0840
0850    stop run.

Lines 0040 - 0070:

0040 select doc           assign address of mybuf
0050                      organization is xml 
0060                      document-type is external doc-type
0070                      file status is doc-status.

Assigns a filename and the buffer mybuf as the source of the XML input, specifies the organization of the file (XML), provides a data-name that variably specifies the XML schema name, and provides a data-name for the file status.

Lines 0080 - 0230:

0080 xd doc.
0090 01  root-tag            identified by root-tag-name.
0100     10  root-tag-name   pic x(80).
0110     10  root-tag-val    pic x(80).
0120     10  root-tag-attr   identified by root-tag-attr-name 
0130                         is attribute.
0140         15  root-tag-attr-name pic x(80).
0150         15  root-tag-attr-val  pic x(80).
0160
0170     10  sub-tag              identified by sub-tag-name.
0180         15  sub-tag-name pic x(80).
0190         15  sub-tag-val  pic x(80).
0200         15  sub-tag-attr identified by sub-tag-attr-name 
0210                          is attribute.
0220             20  sub-tag-attr-val  pic x(80).
0230             20  sub-tag-attr-name pic x(80).

Sets up the record structure of the buffer area.

Lines 0280 - 0370:

0280 01  mybuf.
0290     10  pic x(300) value
0300     '<library location="here" '
0310     &         'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" '
0320     &         'xsi:schemaLocation="library.xsd">'
0330     &    '<book published="yes" goodreading="ok">'
0340     &       'booktext'
0350     &    '</book>'
0360     &    'is a place'
0370     & '</library>'.

Codes the XML stream to be read into a static buffer. While this example has the XML stream coded directly into the program, you could also place the XML into the buffer (mybuf) using any standard input.

Lines 0400 - 0440:

0400     open input doc
0410     read doc
0420     display "Document type is: " doc-type
0430     display "Tag name: " root-tag-name
0440     display "Tag value:" root-tag-val

Opens the buffer area, reads in the XML record, and displays the document type, the name of the root tag, and the value of the root tag.

Line 0450:

0450     start doc key root-tag-attr

Sets the starting point in the buffer to the first attribute for the root tag.

Lines 0500 - 0570:

0500     perform until exit
0510        read doc next key root-tag-attr
0520        if  doc-status not = 0
0530            exit perform
0540        end-if
0550        display "Attribute name : " root-tag-attr-name
0560        display "Attribute value: " root-tag-attr-val
0570     end-perform

Loops through information in the root tag, reading each attribute for the root tag and displaying the attribute names and values.

Line 0600:

0600     start doc key sub-tag

Sets the starting point in the buffer to the first nested tag (non-root tag).

Lines 0610 - 0810

0610     perform until exit
0620        read doc  
0630          next key sub-tag *> index is 1 is default
0640        if  doc-status not = 0
0650            exit perform
0660        end-if
0670        display " Sub tag name: " sub-tag-name
0680        display " Sub tag value:" sub-tag-val 
0690
0700        start doc key sub-tag-attr index is 1
0710        perform until exit
0720            read doc next key sub-tag-attr
0730            if  doc-status not = 0
0740                exit perform
0750            end-if
0760            display " Sub tag attribute name : "
0770              sub-tag-attr-name
0780            display " Sub tag attribute value: " 
0790              sub-tag-attr-val
0800        end-perform
0810    end-perform

Loops through all non-root tags, displaying each XML tag name and value, and all its attribute names and values.

PROCESSING-INSTRUCTION Clause

The PROCESSING-INSTRUCTION clause is provided simply to allow XML processing instructions to be embedded directly within the data associated with a tag. For example, the following code:

    01  my-tag    identified by "my_tag".
        05  my-tag-data1    pic x(80).
        05  my-tag-pi       pic x(80) 
            IS PROCESSING-INSTRUCTION.
        05  my-tag-data2    pic x(80).
    ...
        move 'data' to my-tag-data1 my-tag-data2
        move 'somepi' to my-tag-pi
        write my-tag

Would yield:

    <my_tag>data<?somepi?>data</my_tag>

XML Syntax - PROCESSING-INSTRUCTION Clause

COUNT IN Clause

As shown in the section IDENTIFIED BY and IS ATTRIBUTE Clauses, it is possible to deal with unlimited multiple occurrences of known or unknown tag names through the use of various XML-extended verbs. In less complicated cases where the number of occurrences is known in advance, there are very simple syntax extensions that allow direct addressing.

You can deal with a known number of tag or attribute occurrences using the OCCURS and COUNT IN clauses. The number of acceptable occurrences of a tag or attribute is limited by the OCCURS clause. The COUNT IN clause enables you to determine the number of occurrences received or to specify the number to be sent.

The following example shows how to use the COUNT IN clause:

Example 2: Using OCCURS and COUNT IN clauses

0010  $set preprocess(prexml) warn endp
0020  $set sourceformat(free) case  
0030
0040  select library-file
0050        assign address of mybuf
0060        organization  is xml
0070        document-type is "library.xsd" 
0080        file status is library-status.
0090
0100  data division. 
0110
0120  xd library-file.
0130  01  library            identified by "library".
0140    05  book             identified by "book" 
0150                           occurs 10 times 
0160                           count in library-book-count.
0170        10  book-title  pic x(80) identified by "title".
0180        10  book-author pic x(80) identified by "author".
0190        10  book-toc              identified by "toc".
0200            15  book-toc-section  occurs 20 times
0210                              count in book-section-count
0220                              identified by "section"
0230                              pic x(20).
0240
0250  working-storage section.
0260  01  library-status  pic s999.
0270  01  mybuf.
0280      10  pic x(150) value
0290     '<library>'
0300     & '<book><title>book1</title>'
0310     &'       <toc><section>b1section1</section>'
0320     & '           <section>b1section2</section>'
0330     & '</toc></book>'.
0340      10 pic x(150) value
0350       '<book><title>book2</title>'
0360     & '      <toc><section>b2section1</section>'
0370     & '           <section>b2section2</section>'
0380     & '</toc></book>'
0390     & '</library>'. 
0400
0410  open input library-file
0420  read library-file
0430  perform until library-book-count = 0
0440    display 
0450     "Book title = '" book-title(library-book-count) "'"
0460    display "Number of Sects = " 
0470     book-section-count(library-book-count)
0480     subtract 1 from library-book-count
0490  end-perform
0500  close library-file
0510  stop run.

Lines 0040 - 0080:

0040  select library-file
0050        assign address of mybuf
0060        organization  is xml
0070        document-type is "library.xsd" 
0080        file status is library-status.

Assigns a filename and the buffer mybuf as the source of the XML input, specifies the organization of the file (XML) and provides a filename for the XML schema (library.xsd) and a data-name for the file status.

Lines 0120 - 0230:

0120  xd library-file.
0130  01  library            identified by "library".
0140    05  book             identified by "book" 
0150                           occurs 10 times 
0160                           count in library-book-count.
0170        10  book-title  pic x(80) identified by "title".
0180        10  book-author pic x(80) identified by "author".
0190        10  book-toc              identified by "toc".
0200            15  book-toc-section  occurs 20 times
0210                              count in book-section-count
0220                              identified by "section"
0230                              pic x(20).

Sets up the record structure of the buffer area. Notice the use of OCCURS and COUNT-IN. In this example, the book data-name is identified by the XML tag <book>, it occurs 10 times, and the occurrences are counted in the library-book-count field, which is defined implicitly. The book-toc-section data item is defined similarly, with book-section-count defined implicitly.

Lines 0270 - 0390:

0270  01  mybuf.
0280      10  pic x(150) value
0290     '<library>'
0300     & '<book><title>book1</title>'
0310     &'       <toc><section>b1section1</section>'
0320     & '           <section>b1section2</section>'
0330     & '</toc></book>'.
0340      10 pic x(150) value
0350       '<book><title>book2</title>'
0360     & '      <toc><section>b2section1</section>'
0370     & '           <section>b2section2</section>'
0380     & '</toc></book>'
0390     & '</library>'. 

Codes the XML stream to be read in a static buffer. While this example has the XML stream coded directly into the program, you could also place the XML into the buffer (mybuf) using any standard input.

Lines 0430 - 0490:

0430  perform until library-book-count = 0
0440    display 
0450     "Book title = '" book-title(library-book-count) "'"
0460    display "Number of Sects = " 
0470     book-section-count(library-book-count)
0480     subtract 1 from library-book-count
0490  end-perform

Loops through all records, displaying all book titles and the number of sections contained in each. Notice that book-section-count uses library-book-count as an index.

The COUNT IN clause is also very useful to determine if the tag associated with an element definition was present in the XML stream. A very common use of this is determining which of a set of XD records is read during the execution of a READ statement. For example:

Example 3: Using COUNT IN to determine which record has been read

0010  select book-or-author-file
0020        assign address of mybuf
0030        organization  is xml
0040        document-type is "bookdb.xsd" 
0050        file status is xml-bookdb-status. 
0060
0070  data division.
0080  xd book-or-author-file.
0090  01  book-rec        identified by "book"
0100                      count in book-count.
0110      05  price-val   pic 999.99 identified by "price" 
0120                       is attribute
0130                       count in price-count.
0140      05  title-val   pic x(80) identified by "title".
0150 
0160  01  author-rec      identified by "author" 
0170                       count in author-count.
0180      05  author-val  pic x(80).
0190 
0200  working-storage section.
0210  01  xml-bookdb-status  pic s999.
0220  01  mybuf  pic x(256) value
0230     '<book price="123.00"><title>A title</title></book>'.
0240 
0250  procedure division.
0260     open input book-or-author-file
0270     read book-or-author-file
0280     evaluate true
0290     when book-count = 1
0300         if  price-count not = 0
0310             display "got <book price=" price-val ">
0320               <title>" title-val "</title></book>"
0330         else 
0340             display "got <book><title>" title-val 
0350               "</title></book>"
0360         end-if
0370     when author-count = 1
0380         display "got <author>" author-val "</author>"
0390     end-evaluate
0400     close book-or-author-file
0410     stop run.

Lines 0010 - 0050:

0010  select book-or-author-file
0020        assign address of mybuf
0030        organization  is xml
0040        document-type is "bookdb.xsd" 
0050        file status is xml-bookdb-status. 

Assigns a filename and the buffer mybuf as the source of the XML input, specifies the organization of the file (XML) and provides a filename for the XML schema (bookdb.xsd) and a data-name for the file status.

Lines 0080 - 0180:

0080  xd book-or-author-file.
0090  01  book-rec        identified by "book"
0100                      count in book-count.
0110      05  price-val   pic 999.99 identified by "price" 
0120                       is attribute
0130                       count in price-count.
0140      05  title-val   pic x(80) identified by "title".
0150 
0160  01  author-rec      identified by "author" 
0170                       count in author-count.
0180      05  author-val  pic x(80).

Defines two 01 level items, one for a book record, and one for an author record. Later, the program uses the information defined by COUNT IN to determine which record is being read.

Lines 0220 - 0230:

0220  01  mybuf  pic x(256) value
0230     '<book price="123.00"><title>A title</title></book>'.

Codes the XML stream to be read in a static buffer. While this example has the XML stream coded directly into the program, you could also place the XML into the buffer (mybuf) using any standard input.

Lines 0260 - 0390:

0260     open input book-or-author-file
0270     read book-or-author-file
0280     evaluate true
0290     when book-count = 1
0300         if  price-count not = 0
0310             display "got <book price=" price-val ">
0320               <title>" title-val "</title></book>"
0330         else 
0340             display "got <book><title>" title-val 
0350               "</title></book>"
0360         end-if
0370     when author-count = 1
0380         display "got <author>" author-val "</author>"
0390     end-evaluate

The EVALUATE clause determines which record is being read based on the value of book-count or author-count.

XML Syntax - COUNT IN Clause

NAMESPACE Clause

XML documents often contain namespaces. The NAMESPACE clause enables you to set or identify those namespaces in your COBOL. Specify the NAMESPACE clause in a data description entry. The following example shows how to use the NAMESPACE clause:

Example 4: Using NAMESPACE

0010  xd book-file.
0020  78  book-ns value "http://xml.microfocus.com/book.xsd".
0030  01  book                identified by "book"
0040                          namespace is book-ns.
0050      05  publisher pic x(80)
0060              identified by "name"
0070              namespace is
0080              "http://xml.microfocus.com/publisher.xsd".
0090 
0100      05  author identified by "name"
0110                 namespace is
0120                 "http://xml.microfocus.com/author.xsd".
0130          10  author-first identified by "firstname"
0140                           pic x(80).
0150          10  author-last  identified by "lastname"
0160                           pic x(80).
0170      05  title            identified by "title"
0180                           pic x(80).

Line 0020:

0020  78  book-ns value "http://xml.microfocus.com/book.xsd".

Defines a namespace and its value.

Lines 0030 - 0040:

0030  01  book                identified by "book"
0040                          namespace is book-ns.

Defines a data record with a namespace equivalent to the value in book-ns.

Lines 0050 - 0080:

0050      05  publisher pic x(80)
0060              identified by "name"
0070              namespace is
0080              "http://xml.microfocus.com/publisher.xsd".

Sets a namespace to a fixed URI (Uniform Resource Identifier), which is a specific point of contact on the World Wide Web - in this case an XML schema file.

Lines 0100 - 0120:

0100      05  author identified by "name"
0110                 namespace is
0120                 "http://xml.microfocus.com/author.xsd".

Sets a namespace to a fixed URI.

Lines 0130 - 0160:

0130          10  author-first identified by "firstname"
0140                           pic x(80).
0150          10  author-last  identified by "lastname"
0160                           pic x(80).

Because these data items are in the author group, they take on the same namespace as author.

Lines 0170 - 0180:

0170      05  title            identified by "title"
0180                           pic x(80).

Title inherits the same namespace as book because it is in the book group but does not specify a namespace.

On input, both tags and namespaces must match those in the XML stream. On output, XML tags are qualified by the indicated namespace. The code in Example 0-4 would yield an XML stream similar to:

<?xml version="1.0" encoding="utf-8" ?>
<book xmlns="http://xml.microfocus.com/book.xsd">
   <name xmlns="http://xml.microfocus.com/publisher.xsd">
      Just a publisher
   </name>
   <name xmlns="http://xml.microfocus.com/author.xsd">
      <firstname>AuthorFirstname</firstname>
      <lastname>AuthorFirstname</lastname>
   </name>
   <title>
      This is the title
   </title>
</book>

You can replace a specific NAMESPACE value with a data-name. This facilitates dynamic discovery of a namespace in XML. In this case, namespace matching is not performed on input. Instead, the namespace of the matching tag is populated into the data item specified by NAMESPACE. On output, the value of the namespace referenced by the data-name is used to qualify the output tag. The following record:

     xd generic-file.
     01  generic-tag identified by generic-tag-name
                     namespace is generic-tag-namespace.
         05  generic-tag-name           pic x(80).
         05  generic-tag-namespace      pic x(80).
         05  generic-tag-value          pic x(80).

and XML stream input:

   <name xmlns="http://xml.microfocus.com/publisher.xsd">
      Just a publisher
   </name>

yields the value of "name" for generic-tag-name, the value of "http://xml.microfocus.com/publisher.xsd" for generic-tag-namespace and the value of "Just a publisher" for generic-tag-value.

XML Syntax - NAMESPACE clause

COBOL Verbs

Some familiar COBOL verbs have also been extended to handle XML. They are:

Techniques for CGI-Based Applications

You can directly use XML syntax extensions to create a client for an XML-enabled CGI-based application by using the ASSIGN "http://...." syntax in your client. The following is an example of program that creates a client for a CGI-based program, calccgi, running on the local host:

Example 5: Client-side application with XML syntax extensions

0010  $set preprocess(prexml) o(calc.pp) endp
0020
0030  program-id. "calc".
0040  select xml-calc
0050        assign "http://localhost/cgibin/calccgi.exe" 
0060        organization is xml 
0070        document-type is "calc.xsd" 
0080        file status is xml-calc-status.
0090
0100  data division.
0110  xd  xml-calc.
0120	 01  xml-record identified by "request"
0130				           count in xml-record-check.
0140		    05  xml-num-1 pic 99 identified by "num1".
0150		    05  xml-num-2 pic 99 identified by "num2".
0160		    05  xml-func pic x(3) identified by "func".
0170		    05  xml-result pic ----9 identified by "result".
0180
0190  working-storage section.
0200  01  xml-calc-status pic s9(9) comp-5.
0210
0220  procedure division.
0230
0240	 open i-o xml-calc
0250	 if xml-calc-status not = 0
0260		  display "Error opening channel"
0270		  stop run
0280	 end-if
0290
0300	 move "subtract" to xml-func
0310	 move 2 to xml-num-1
0320	 move 3 to xml-num-2
0330	 perform doit
0340
0350	 move "add" to xml-func
0360	 perform doit
0370
0380	 close xml-calc
0390	 stop run.
0400
0410  doit section.
0420
0430 	write xml-record
0440 	display "Function call :" xml-func
0450	 if xml-calc-status < 0
0460		  exhibit named xml-calc-status
0470		  stop run
0480	 end-if
0490
0500	 read xml-calc
0510
0520	 if xml-calc-status < 0
0530		  exhibit named xml-calc-status
0540		  stop run
0550	 end-if
0560
0570	 if xml-record-check > 0 *> Output 
0580		  exhibit named xml-num-1
0590		  exhibit named xml-num-2
0600		  exhibit named xml-func
0610		  exhibit named xml-result
0620	 end-if.

Line 0040 - 0080:

0040  select xml-calc
0050        assign "http://localhost/cgibin/calccgi.exe" 
0060        organization is xml 
0070        document-type is "calc.xsd" 
0080        file status is xml-calc-status.

Assigns a CGI application to xml-calc.

This next example is of a matching server-side program that services this client. Notice the use of the ":CGI:" filename. The ":CGI:" assignment instructs the run-time system to respect the CGI standard CONTENT_LENGTH environment variable.

Example 6: Server-side CGI application with XML syntax extensions

0010      $set preprocess(prexml) o(calccgi.pp) endp
0020
0030	program-id. "calccgi".
0040
0050	select xml-calc assign ":CGI:"
0060		organization is xml 
0070		document-type is "calc.xsd" 
0080		file status is xml-calc-status.
0090
0100	data division.
0110 xd xml-calc.
0120	01 xml-record identified by "request"
0130				count in xml-record-check.
0140		  05 xml-num-1 pic 99 identified by "num1".
0150		  05 xml-num-2 pic 99 identified by "num2".
0160		  05 xml-func pic x(3) identified by "func".
0170		  05 xml-result pic ----9 identified by "result".
0180
0190	working-storage section.
0200	01 xml-calc-status pic s9(9) comp-5.
0210
0220	procedure division.
0230
0240		  open input xml-calc
0250		  if xml-calc-status not = 0
0260			  display "Error opening input channel"
0270			  stop run
0280		  end-if
0290
0300		  read xml-calc
0310
0320		  if xml-calc-status < 0
0330			  exhibit named xml-calc-status
0340			  display "Error reading channel "
0350			  stop run
0360		  end-if
0370
0380		  if xml-record-check > 0 *> Input was correct
0390			  close xml-calc
0400
0410			  open output xml-calc
0420			  if xml-calc-status not = 0
0430				  display "Error opening output channel"
0440				  stop run
0450			  end-if
0460
0470			  evaluate true
0480			  when xml-func = "add"
0490				  add xml-num-2 to xml-num-1
0500						  giving xml-result
0510			  when xml-func = "sub"
0520				  subtract xml-num-2 from xml-num-1
0530						  giving xml-result
0540			  when xml-func = "mul"
0550				  multiply xml-num-1 by xml-num-2
0560						  giving xml-result
0570			  when xml-func = "div"
0580				  divide xml-num-1 by xml-num-2
0590						  giving xml-result
0600			  end-evaluate
0610
0620			  write xml-record key is plain-text 
0630        "Content-type: text/xml" & x"0d0a"
0640			  write xml-record
0650		  end-if
0660		  close xml-calc.
0670		  stop run.

Line 0050 - 0080:

0050	select xml-calc assign ":CGI:"
0060		organization is xml 
0070		document-type is "calc.xsd" 
0080		file status is xml-calc-status.

Using the ":CGI:" filename is critical, as input to a CGI program is undefined if there is an attempt to read more data than specified in the CGI CONTENT_LENGTH value. The ":CGI:" assignment instructs the run-time system to respect this variable.

Line 0380:

0380		  if xml-record-check > 0 *> Input was correct

xml-record-check holds the number of data items in the stream. If it is greater than zero, then the execution of the READ statement did find data.

Lines 0390 - 0410:

0390			  close xml-calc
0400
0410			  open output xml-calc

This closes the XML input stream and reopens it as an output stream. A CGI application typically opens ":CGI:" in input mode to read the XML data, closes that input stream, and then opens ":CGI:" in output mode to produce output.

Line 0620:

0620			  write xml-record key is plain-text 

Under some Web servers the PLAIN-TEXT value "Content-type: text/xml" is a required prefix to any CGI output.

Compiling XML-enabled COBOL

To compile or build COBOL that has been XML-enabled using XML syntax extensions, the code must be preprocessed by the XML preprocessor in your COBOL development system. This is a necessary step that enables the Compiler to recognize the XML syntax you've coded into your program.

You compile or build XML-enabled COBOL in one of two ways:

Compiling for the Server Express IDE

Before you build your XML-enabled COBOL from the IDE, you must insert the following code on the first line of your program before the Identification Division:

$set {preprocess | p}(prexml) [{out | o} (outname)] [warn] 
     [{preprocess | p} (ppname)] endp

where the parameters are:

{preprocess | p} The pre-processor to be used.
{out | o} outname The fully preprocessed output source file, outname. This output source file contains native COBOL processed from the XML syntax.
warn Cause diagnostic warnings on parsing to be presented by PREXML.
ppname The preprocessor name you want to use to read source files and process COPY statements. Preprocessors can be nested.

For example:

$set p(prexml) warn endp

Compiling from the Command Line

If you have the $set statement coded into your program, then you compile from the command line just as you would a program that is not XML enabled. However, if you do not have the $set statement coded into your program, or you would like to override all of the parameters specified in your $set statement, specify a command line as follows:

cob programname.cbl -C "{preprocess | p}(prexml)
        [{out | o} (outname)]
        [warn]
        [{preprocess | p} (ppname)]
        endp"

where programname is the file prefix of the COBOL program you are compiling, and the other parameters are the same as those used with the $set statement. See the section Building from Server Express above for an explanation of these parameters.

For example:

cob foo.cbl -C "p(prexml) warn endp"