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:
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:
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.