Uploaded by Viktor G.

Batch modernization in z OS by the examp

advertisement
Batch modernization
in z/OS by the example
The Batch modernization made simple.
Batch modernization in z/OS by the example : The Batch modernization made simple.
Table of Contents
By the same author ............................................................................................................. v
Preface: The Batch modernization move ................................................................................ vi
1. Cobol and Java ............................................................................................................... 1
1. TstHello example 1 .................................................................................................. 2
1.1. Create the Cobol program TSTHELLO ............................................................. 3
1.2. Create the Jcl JCOBOL and submit it ............................................................... 4
1.3. In the USS generate HelloJ class ..................................................................... 7
1.4. In the TSO/E environment execute TSOHELLO module and review your outputs ................................................................................................................... 8
1.5. Possible causes of errors ................................................................................ 9
2. TstHello example 2 ................................................................................................ 10
2.1. Copy the Cobol program to /a/userid location in the USS. ................................... 11
2.2. Create the TstHello.bat script file ................................................................... 12
2.3. Execute TstHello.bat .................................................................................... 14
2.4. Possible causes of errors. .............................................................................. 15
3. TstHello example 3 ................................................................................................ 16
3.1. Create the TstHelloJ.java program in /a/userid/myjava ........................................ 17
3.2. Create a modified TstHello.cbl program in sub-directory ooHello ......................... 18
3.3. Create the TstooHello.bat script ..................................................................... 20
3.4. Execute the script ........................................................................................ 22
3.5. The generated TstooHello.java source ............................................................. 23
3.6. Possible causes of errors. .............................................................................. 24
4. The oosample example ........................................................................................... 25
4.1. The structure of the application ...................................................................... 26
4.2. The Cobol main program TestAccounts.cbl ...................................................... 27
4.3. The Cobol program Account.cbl .................................................................... 29
4.4. The Cobol program CheckingAccount.cbl ........................................................ 32
4.5. The Check java program ............................................................................... 35
4.6. The oosample.bat script file .......................................................................... 36
4.7. Execute the script ........................................................................................ 38
2. Cobol, XML and XSD .................................................................................................... 39
1. The XMLCOB1 example ........................................................................................ 40
1.1. The Cobol program ..................................................................................... 41
1.2. The XSD processing .................................................................................... 66
1.3. The build of the module and its execution ....................................................... 69
2. The XMLQRY1 example ........................................................................................ 72
2.1. The Cobol program ..................................................................................... 73
2.2. The build of the module and its execution ....................................................... 90
3. C++ and XML .............................................................................................................. 91
1. Try the pre-installed IBM samples programs ............................................................... 92
2. Generate and execute the samples in the USS ............................................................. 94
2.1. Get and install the GNU gmake utility ............................................................ 95
2.2. Prepare your environment ............................................................................. 96
2.3. Configure and execute gmake ........................................................................ 97
2.4. Script the build of the examples ..................................................................... 98
2.5. Script the execution of the examples ............................................................... 99
3. Generate in the USS to a Z/OS load library and execute in Z/OS ................................... 104
3.1. Install gmake ............................................................................................ 105
3.2. Prepare your environment ........................................................................... 106
3.3. Prepare the Configure script ........................................................................ 107
3.4. Prepare a gmake script ............................................................................... 108
iii
Batch modernization
in z/OS by the example
3.5. Execute the scripts and loadmodules in a Z/OS batch job ..................................
4. Fully generate an example in Z/OS .........................................................................
5. How to use the z/OS specific parser classes ..............................................................
5.1. Generate zsamples .....................................................................................
5.2. Execute zsamples in the USS .......................................................................
5.3. Generate zsamples in Z/OS .........................................................................
5.4. Execute zsamples in Z/OS ...........................................................................
6. How to use the XSLT Processor, C++ Edition ...........................................................
6.1. Generate the xslt examples in the USS ..........................................................
6.2. Execute the xslt examples in the USS ............................................................
6.3. Generate the xslt examples to Z/OS ..............................................................
6.4. Execute the xslt examples in Z/OS ...............................................................
6.5. Fully generate a xslt example in Z/OS ...........................................................
6.6. Execute the Xalan transformer directly ..........................................................
6.7. Execute the test XSLT utility .......................................................................
7. How to call the XML Toolkit from a Cobol program ..................................................
7.1. Set up the test files for the SPFEXML application ...........................................
7.2. The SPFEXML cobol program .....................................................................
7.3. The A1CCDLGT program ...........................................................................
7.4. The SAXPRSE program .............................................................................
7.5. The SAXHNDL program ............................................................................
7.6. The SAXPRSEH include ............................................................................
7.7. The SAXHNDLH include ...........................................................................
7.8. The JCL ...................................................................................................
7.9. The outputs produced by the SPFEXML application ........................................
4. Conclusion ..................................................................................................................
iv
109
115
120
121
122
125
126
127
128
129
131
132
133
138
140
142
143
144
147
149
153
155
157
159
163
164
By the same author
• Batch modernization in z/OS by the example as a web document: http://patrice.cotte.free.fr/techpages/bmv1/index.html
• MyDocbook or how turn your Eclipse IDE into a publishing environment: http://patrice.cotte.free.fr/
techpages/mydocbook/index.html
For an easier reading the author recommends to browse the web formatted versions of these books.
v
Preface: The Batch modernization
move
The 'Batch modernization on z/OS' is IBM's response to make the Mainframe world more in phase with the
distributed world, which includes the use of XML and inter-operability between languages, cross-platform
generation and execution. IBM has published a number of manuals on the subject.
• Redbook Batch Modernization on z/OS, SG24-7779-01, July 2012
• Redbook New Ways of Running IBM z/OS Batch Applications, SG24-8116-00,n May 2013
• Redbook New Ways of Running IBM z/OS Batch Applications, Volume 1 CICS Transaction Server,
SG24-7991-00, October 2013
• Redbook New Ways of Running IBM z/OS Batch Applications, Volume 4 IBM IMS, SG24-8119-00,
May 2014
To this day there is no Volume 2 and no Volume 3.
These manuals come in addition to
• The Enterprise COBOL for z/OS V4.2 Programming Guide, SC23-8529-01, 2001-2009
• The XML Processing on z/OS,SG24-7810-00, December 2009
• XML Toolkit for z/OS User's guide
All these publications contain many examples of the new ways to execute applications in a z/OS system.
While these examples focus on the coding the generation and setup of the examples is often confusing and
not enough documented. This is where this books comes in.
This manual very simply explains how to implement a number of these examples:
• Chapter 1 - Cobol and Java
• Generate and execute the Cobol and Java TstHello application in various ways.
• Generate and execute the Cobol and Java oosample application in the USS.
• Chapter 2 - Cobol, XML and XSD
• Generate and execute the Cobol XMLCOB1 program.
• Generate and execute the Cobol XMLQRY1 program.
• Chapter 3 - The XML Parser, C++ Edition
• Generate the xslt examples in the USS.
• Execute the xslt examples in the USS.
• Generate the xslt examples to z/OS.
• Execute the xslt examples in Z/OS.
vi
Preface: The Batch
modernization move
• Fully generate an xslt example in Z/OS.
• Execute the Xalan transformer directly.
• Execute the test XSLT utility.
• Call the XML Toolkit from a Cobol program.
vii
Chapter 1. Cobol and Java
This chapter gathers a number of examples that demonstrate how Cobol and Java can interoperate.
• TstHello example 1: Cobol program TSTHELLO is generated and run in TSO/E, calls Java class HelloJ
in the USS
• TstHello example 2: Cobol program TSTHELLO and Java class HelloJ are generated and run in the USS
• TstHello example 3: Java program TstHelloJ calls OO Cobol TSTHELLO that calls Java class HelloJ,
in the USS
1
Cobol and Java
1. TstHello example 1
Reference
Enterprise Cobol Programming Guide V4R2, chapter 16, Compiling, linking and running OO applications.
Requirements
• User has access to the TSO/E environment and the IBM Cobol compiler at level V4 or higher
• User has access to the USS
2
Cobol and Java
1.1. Create the Cobol program TSTHELLO
This source will be stored as a member of a library in the TSO/E environment.
cbl thread,dll
IDENTIFICATION DIVISION.
Program-id. "TSTHELLO" recursive.
* ---------------------------------------------------------* This example has been copied from the Enterprise Cobol
* Programming guide V4R2, chapter 16, Compiling, linking and
* running OO applications.
* ---------------------------------------------------------Environment division.
Configuration section.
Repository.
Class HelloJ is "HelloJ".
Data division.
Procedure division.
Display "COBOL program TSTHELLO entered."
* **
Java is invoked, not called!
Invoke HelloJ "sayHello"
Display "COBOL program TSTHELLO returned from Java."
Goback
.
End program "TSTHELLO".
Note the following
• Cbl options thread,dll
• HelloJ java program is define as a class in the Repository section (OO Cobol)
• HelloJ is invoked , not called
3
Cobol and Java
1.2. Create the Jcl JCOBOL and submit it
This Jcl will be stored as a member of a library in the TSO/E environment.
//USERIDC JOB accnt,'ENTERPRISE COBOL',CLASS=A,
//* TYPRUN=SCAN,
//*
RESTART=GO,
//
MSGCLASS=X,
//JCOBOL
PROC COBOLHQ='',
//
SRCFILE='',
//
JVMBR='',
//
MEMBER='',
//
CPARM='',
//
LPARM='',
//
LOADLIB=''
//*
//COB2
EXEC PGM=IGYCRCTL,REGION=512K,
//
PARM=&CPARM
//STEPLIB DD DISP=SHR,DSN=&COBOLHQ..SIGYCOMP
//SYSLIB
DD DISP=SHR,DSN=&COBOLHQ..SIGYMAC
//
DD DISP=SHR,DSN=CEE.SCEESAMP
//SYSLIN
DD DSN=&&LOADSET,DISP=(,PASS),UNIT=VIO,
//
SPACE=(TRK,(5,2)),
//
DCB=(RECFM=FB,LRECL=80,BLKSIZE=2960)
//SYSPRINT DD SYSOUT=*,DCB=(LRECL=121,BLKSIZE=3630,RECFM=FBA)
//SYSMDECK DD SYSOUT=*
//SYSPUNCH DD DUMMY
//* --------------------- SYSJAVA ALLOCATION IS FOR OO COBOL
//SYSJAVA DD PATH='/a/userid/myjava/&JVMBR..java',
// PATHOPTS=(OWRONLY,OCREAT,OTRUNC),
// PATHDISP=KEEP,
// PATHMODE=SIRWXU,
// FILEDATA=TEXT
//* --------------------------------------------------------//SYSTERM DD UNIT=VIO,SPACE=(TRK,(5,2))
//SYSUT1
DD UNIT=VIO,SPACE=(CYL,(2,1))
//SYSUT2
DD UNIT=VIO,SPACE=(CYL,(2,1))
//SYSUT3
DD UNIT=VIO,SPACE=(CYL,(2,1))
//SYSUT4
DD UNIT=VIO,SPACE=(CYL,(1,1))
//SYSUT5
DD UNIT=VIO,SPACE=(CYL,(1,1))
//SYSUT6
DD UNIT=VIO,SPACE=(CYL,(1,1))
//SYSUT7
DD UNIT=VIO,SPACE=(CYL,(1,1))
//*
----------------------------------------------- SYSIN
//SYSIN
DD DISP=SHR,DSN=&SRCFILE(&MEMBER)
//*
//******************************************************************130*
//*
LINK THE GENERATED PROGRAM
*
//**********************************************************************
//*
//LKED
EXEC PGM=HEWL,REGION=512K,
//
PARM=&LPARM
//SYSLIB
DD DISP=SHR,DSN=CEE.SCEELKED
4
Cobol and Java
//
DD DISP=SHR,DSN=CEE.SCEELKEX
//
DD DISP=SHR,DSN=CEE.SCEELIB
<< IGZCJAVA
//
DD DISP=SHR,DSN=&COBOLHQ..SIGYCOMP
//SYSLIN
DD DSN=&&LOADSET,DISP=(OLD,DELETE)
//SYSPRINT DD SYSOUT=*,DCB=(LRECL=121,BLKSIZE=3630,RECFM=FBA)
//SYSUT1
DD UNIT=VIO,SPACE=(TRK,(5,2))
//*
----------------------------------------- SYSLMOD
//SYSLMOD DD DISP=SHR,DSN=&LOADLIB(&MEMBER)
//*
//
PEND
//**********************************************************************
//*
COMPILE and LINK program
*
//**********************************************************************
//COMPLINK EXEC JCOBOL,
//
JVMBR='HelloJ',
//
MEMBER='TSTHELLO',
//
SRCFILE='userid.COBOL.SRC',
//
COBOLHQ='Z/OSSYS.COBOL.V4R2M0.PDO0939',
//
LOADLIB='userid.COBOL.DLLLIB',
//
CPARM='(SOURCE,XREF,LIST,LIB,APOST,NOSEQ,RENT,MDECK)',
//
LPARM='(XREF,LIST,RENT,LET,DYNAM(DLL),CASE(MIXED))'
//LKED.SYSLIN
DD DSN=&&LOADSET,DISP=(OLD,DELETE)
//
DD *
INCLUDE '/usr/lpp/java/J7.1/bin/j9vm/libjvm.x'
* INCLUDE '/usr/lpp/cobol/lib/igzcjava.x'
* INCLUDE IGZCJAVA
IMPORT CODE,'IGZCJAVA','GetClassObject'
IMPORT CODE,'IGZCJAVA','GetEnvPtr'
IMPORT CODE,'IGZCJAVA','GetInstanceData'
IMPORT CODE,'IGZCJAVA','GetJVMPtr'
/*
//**********************************************************************
//*
RUN program
*
//**********************************************************************
//GO EXEC PGM=TSTHELLO,COND=((4,LT,COMPLINK.COB2),
//
(4,LT,COMPLINK.LKED)),
//
PARM='/ENVAR("_CEE_ENVFILE=/a/userid/myjava/ENV")
//
POSIX(ON),XPLINK(ON)'
//STEPLIB DD
DISP=SHR,DSN=userid.COBOL.DLLLIB
//SYSOUT
DD
SYSOUT=*
//SYSPRINT DD
SYSOUT=*
//JAVAIN
DD
DUMMY
//JAVAOUT DD
PATH='/a/userid/myjava/thjavaout',
// PATHOPTS=(OWRONLY,OCREAT,OTRUNC),
// PATHMODE=(SIRUSR,SIWUSR,SIRGRP)
//JAVAERR DD
PATH='/a/userid/myjava/thjavaerr',
// PATHOPTS=(OWRONLY,OCREAT,OTRUNC),
// PATHMODE=(SIRUSR,SIWUSR,SIRGRP)
//
Note the following
5
Cobol and Java
• This job (re)creates HelloJ.java empty in SYSJAVA location the USS
• If igzcjava.x does not exist a copy exists as IGZCJAVA in the CEE.SCEELIB library
• The igzcjava.x file only contains a list of IMPORTs. Aternatively you can add them to the SYSLIN
• This job creates a DLL, which means the output library SYSLMOD must be a PDSE
Because class HelloJ will be (re)created empty you should submit your JCL leaving out the GO step. Once
your HelloJ class is ready use again that JCL to submit the GO step only.
6
Cobol and Java
1.3. In the USS generate HelloJ class
• Edit /a/userid/HelloJ.java and add these lines
class HelloJ {
public static void sayHello() {
System.out.println("Hello World, from Java!");
}
}
• Compile HelloJ.java into HelloJ.class
javac HelloJ.java
• Create /a/userid/myjava/ENV environment file with this contents
PATH=/bin:/usr/lpp/java/J7.1/bin
LIBPATH=/lib:/usr/lib:/usr/lpp/java/J7.1/bin:/usr/lpp/java/J7.1/bin/j9vm
CLASSPATH=/a/userid/myjava:/usr/lpp/java/J7.1/bin/j9vm
7
Cobol and Java
1.4. In the TSO/E environment execute TSOHELLO module and review your outputs
Edit the JCOBOL jcl and use the RESTART parameter in the job card to execute the GO step only
//GO EXEC PGM=TSTHELLO,COND=((4,LT,COMPLINK.COB2),
//
(4,LT,COMPLINK.LKED)),
//
PARM='/ENVAR("_CEE_ENVFILE=/a/userid/myjava/ENV")
//
POSIX(ON),XPLINK(ON)'
//STEPLIB DD
DISP=SHR,DSN=userid.COBOL.DLLLIB
//SYSOUT
DD
SYSOUT=*
//SYSPRINT DD
SYSOUT=*
//JAVAIN
DD
DUMMY
//JAVAOUT DD
PATH='/a/userid/myjava/thjavaout',
// PATHOPTS=(OWRONLY,OCREAT,OTRUNC),
// PATHMODE=(SIRUSR,SIWUSR,SIRGRP)
//JAVAERR DD
PATH='/a/userid/myjava/thjavaerr',
// PATHOPTS=(OWRONLY,OCREAT,OTRUNC),
// PATHMODE=(SIRUSR,SIWUSR,SIRGRP)
//
The job executes with a Return code 0. The SYSOUT shows
COBOL program TSTHELLO entered.
COBOL program TSTHELLO returned from Java.
In the USS the /a/userid/myjava/thjavaout output shows
Hello World, from Java!
8
Cobol and Java
1.5. Possible causes of errors
At link time, unresolved references.
• In the USS, navigate to the Java location and make sure libjvm.x exists
• In the USS, navigate to the cobol location and make sure igzcjava.x exists. You can work around this
issue by adding the IMPORTS as shown above.
At execution time the job abends with a S0C1 abend code, a CEE3501S LE code and message 'libjvm.so
not found'. Check out the ENV file is configured as above
At execution time the job issues a 'main thread Exception' with a message stating the application is not
XPLINK compatible. Make sure the GO step specifies XPLINK(ON)
9
Cobol and Java
2. TstHello example 2
Although not explained in the Programming Guide, Chapter 16, Section "Compiling, linking and running
OO applications under z/OS UNIX" it is possible to generate and execute the Cobol program entirely in
the USS. This information has been made available by Robert Sample on October 14, 2010 in the IBM
Mainframe forum.
Requirements
• The IBM Cobol compiler at level V4 or higher
• User has access to the USS
• The cobol product has been installed in the USS, the usual location is usr/lpp/cobol
10
Cobol and Java
2.1. Copy the Cobol program to /a/userid location in the
USS.
cbl thread,dll
IDENTIFICATION DIVISION.
Program-id. "TSTHELLO" recursive.
* ---------------------------------------------------------* This example has been copied from the Enterprise Cobol
* Programming guide V4R2, chapter 16, Compiling, linking and
* running OO applications.
* ---------------------------------------------------------Environment division.
Configuration section.
Repository.
Class HelloJ is "HelloJ".
Data division.
Procedure division.
Display "COBOL program TSTHELLO entered."
* **
Java is invoked, not called!
Invoke HelloJ "sayHello"
Display "COBOL program TSTHELLO returned from Java."
Goback
.
End program "TSTHELLO".
Note the following
• The cobol program is identical to the cobol program in TSO/E
• The HelloJ class does not need a rebuild if it was generated for the prior example.
11
Cobol and Java
2.2. Create the TstHello.bat script file
#
# This script compiles, links the TstHello cobol program and
# executes the resulting library libTstHello.so
#
# - XPLINK(ON) run options is required.
#
# - Xmls and Xmx must be bigger than 1M in order to initialize
# the JVM.
#
# - append -verbose:gc
to COBJVMINIOPTIONS to get the detail
# of the IBM JVM garbage collection on screen.
#
# - append -Xverbosegclog:name.lst to COBJVMINIOPTIONS to get the detail
# of the IBM JVM garbage collection written to file name.lst
#
JAVASIDEDECKPATH=${JAVA_HOME}/bin/classic
COBSIDEDECKPATH=/sys/cobol/V5R1M0/usr/lpp/cobol/lib
COBCOPYPATH=/sys/cobol/V5R1M0/usr/lpp/cobol/include
export COBJVMINITOPTIONS="-Xms1200000 -Xmx1200000 -Xverbosegclog:TstHell
export _CEE_RUNOPTS="XPLINK(ON)"
#
# ------------------------------------------------------------------# cob2 cheatsheet:
# -bdll
the executable module is a DLL
# -c
compile no link
# -Ipath
names a path for the copybook search
# -o name
names the object module
# -qopt,opt, compiler options
# -v
verbose, echoes the commands that cob2 generates
# -#
displays compile and link steps without execution
#
# Compile TstHello.cbl into TstHello.o + TstHello.java.
# The report goes to TstHello.lst
#
# cob2 syntax: see the Enterprise Cobol Programming Guide chapter 15.
#
the cob2 report always goes to xxxx.lst output
#
cob2 -c -qdll,thread I${COBCOPYPATH} TstHello.cbl
#
# Link
TstHello.o
into dll libTstHello.so
# The report goes to TstHellolnk.lst
#
cob2 -V -bdll,map,list
-o libTstHello.so TstHello.o
${JAVASIDEDECKPATH}/libjvm.x
${COBSIDEDECKPATH}/igzcjava.x>TstHellolnk.lst
#
# Execute libTstHello.so
#
./libTstHello.so
12
Cobol and Java
Note the following
• The cob2 -V command has been split over three lines for an easier reading. It must actually be a single
line.
• The 'so' file name must be the prefix 'lib' with the name of the program concatenated.
13
Cobol and Java
2.3. Execute TstHello.bat
The execution of the script produces a number of lines similar as the below ones.
PP 5655-S71 IBM Enterprise COBOL for z/OS 4.2.0 in progress ...
End of compilation 1, program TSTHELLO, no statements flagged.
IGD01008I ALLOCATION SET TO SCTEMPD M0610
IGD01010I ALLOCATION SET TO SGTEMPD STORAGE GROUP
IGD01008I ALLOCATION SET TO SCTEMPD M0610
IGD01010I ALLOCATION SET TO SGTEMPD STORAGE GROUP
IEW2617I 4C43 DEFINITION SIDE FILE IS EMPTY. THERE ARE NO SYMBOLS TO BE
EXPORTED.
COBOL program TSTHELLO entered.
Hello World, from Java!
COBOL program TSTHELLO returned from Java.
USERID:/a/userid/myjava: >
14
Cobol and Java
2.4. Possible causes of errors.
Command cob2 not found.
• Check out the cobol product is installed.
• Check out the path (for example in .profile) contains the location of the cob2 executable.
Unresolved references at link time.
• Check out the PATH variables are correct.
• Check out libjvm.x and igzcjava.x exist.
Errors at execution time.
• JVM initialization errors, Xms or Xmx too small. Adjust these values in the COBJVMINITOPTIONS
• Application noXPLINK attempts to call an XPLink class. Check out the _CEE_RUN_OPTS variable.
15
Cobol and Java
3. TstHello example 3
In this example Java program TstHelloJ calls TstooHello cobol program that invokes HelloJ as seen in the
prior sections. It is assumed the current location in the USS is /a/userid/myjava
Requirements
• The IBM Cobol compiler at level V4 or higher
• User has access to the USS
• The cobol product has been installed in the USS, its usual location is usr/lpp/cobol
16
Cobol and Java
3.1. Create the TstHelloJ.java program in /a/userid/myjava
/*
* TstHelloJ java program is
* mixed application.
*
* TstHelloJ java class
* >> creates an instance of
*
Cobol TstooHello cobol
*
>> TstooHello calls
*
*/
import ooHello.*;
public class TstHelloJ {
the top program in a Cobol and java
TstooHello, a class derived from
program
java class HelloJ
public static void main(String [] args){
int rc = 0;
System.out.println("TstHelloJ main is executing!");
// Create instance of TstooHello class
TstooHello tsth = new TstooHello();
System.out.println("TstHelloJ has created TstooHello object");
// Invoke method
of TstooHello class
tsth.CallHelloJ();
}
}
17
Cobol and Java
3.2. Create a modified TstHello.cbl program in sub-directory ooHello
Create ooHello folder in /a/userid/myjava location
Create TstooHello.cbl program in ooHello folder
cbl thread,dll,pgmname(longmixed)
IDENTIFICATION DIVISION.
* -----------------------------------------------------------* This example has been copied from the Enterprise Cobol
* Programming guide V4R2, chapter 16, Compiling, linking and
* running OO applications.
* -----------------------------------------------------------Class-id. TstooHello inherits Base.
Environment division.
Configuration section.
Repository.
Class Base
is "java.lang.Object"
Class HelloJ is "HelloJ"
Class TstooHello is "ooHello.TstooHello".
* -----------------------------------------------------------* Note TstooHello appears also as a class "ooHello.TstooHello"
* This determines the setup of package ooHello in the generated
* java source TstooHello.
* -----------------------------------------------------------* Class definition
Identification division.
Object.
Data division.
Working-storage section.
Procedure division.
* Define a method.
Identification division.
Method-id. 'CallHelloJ'.
Data division.
Linkage section.
Procedure division.
Display "COBOL program TSTOOHELLO entered."
* **
Java is invoked, not called!
Invoke HelloJ "sayHello"
Display "COBOL program TSTOOHELLO returned from Java."
Goback
.
End Method 'CallHelloJ'.
*
18
Cobol and Java
End Object.
End Class TstooHello.
Note the following
• TstooHello.cbl is an OO (Object Oriented) program with a class, an object and a method
• The repository defines class TstooHello as "ooHello.TstooHello". This instructs the cob2 compiler to
create package ooHello in the corresponding TstHello.java program.
• Method CallHelloJ contains Cobol displays around the invocation of the HelloJ java class
19
Cobol and Java
3.3. Create the TstooHello.bat script
#
# Script TstooHello.bat compiles and links the TstHelloJ class and
# the TstooHello.cbl cobol program.
#
JAVASIDEDECKPATH=${JAVA_HOME}/bin/classic
COBSIDEDECKPATH=/sys/cobol/V5R1M0/usr/lpp/cobol/lib
COBCOPYPATH=/sys/cobol/V5R1M0/usr/lpp/cobol/include
#
# ------------------------------------------------------------------# cob2 cheatsheet:
# -bdll
the executable module is a DLL
# -c
compile no link
# -Ipath
names a path fot copybook search
# -o name
names the object module
# -qopt,opt, compiler options
# -v
verbose, echoes the commands that cob2 generates
# -#
displays compile and link steps without execution
# ------------------------------------------------------------------# Java and Cobol have different requirements regarding 'subroutines'.
#
# The Java caller can only call a Cobol through a package, which
# leads to the following:
#
# - The cobol program defines classes using the package.name format.
#
>> cob2 then creates a java program with the corresponding
#
package name.
#
>> a directory with the same name as the package must exist in
#
the current location.
#
>> the resulting library must contain the package name
#
('lib' + package-name + '-' + cobol-name + '.so'.
#
the library must reside in the package directory.
#
#
See Link #1 below.
#
# - The java caller must import the cobol package. When the class
#
is created it is searched under its true name so we also need
#
a library under the Cobol program name.
#
#
See Link #2 below.
#
# ------------------------------------------------------------------# Compile TstooHello.cbl into TstooHello.o + TstooHello.java.
# The report goes to TstooHello.lst
#
# cob2 syntax: see the Enterprise Cobol Programming Guide chapter 15.
#
cob2 -c -bdll ./ooHello/TstooHello.cbl
#
# Link #1 TstooHello.o into dll libooHello_TstooHello.so
# The report goes to TstooHellolnk.lst
20
Cobol and Java
#
cob2 -bdll,map,list,xref -o ./ooHello/libooHello_TstooHello.so
TstooHello.o ${JAVASIDEDECKPATH}/libjvm.x
${COBSIDEDECKPATH}/igzcjava.x
>TstooHellolnk.lst
#
# Link #2 TstooHello.o into dll libTstooHello.so
# The report goes to TstooHellolnk.lst
#
cob2 -bdll,map,list,xref -o ./ooHello/libTstooHello.so
TstooHello.o ${JAVASIDEDECKPATH}/libjvm.x
${COBSIDEDECKPATH}/igzcjava.x
>TstooHellolnk.lst
#
# Move the generated class to the ooHello directory
#
mv TstooHello.java ooHello
#
# Create TstooHello class
#
javac ooHello/TstooHello.java
#
# Build TstHelloJ java class
#
javac TstHelloJ.java
#
# Execute the application
#
java -Djava.library.path="/a/userid/myjava/ooHello" TstHelloJ
Note the following
• cob2 lines appear on several lines for an easier reading. They are actually single lines commands
• ooHello folder must exist in /a/userid/myjava
• The cobol program is linked first in order to create the libooHello_TstooHello.so library
• The cobol program is linked again in order to create the libTstooHello.so library
• TstHelloJ class is finally passed to java for execution along with a Dparm
21
Cobol and Java
3.4. Execute the script
The execution of the script produces a few lines similar to the below ones.
USERID:/a/userid/myjava: >TstooHello.bat
PP 5655-S71 IBM Enterprise COBOL for z/OS 4.2.0 in progress ...
End of compilation 1, class TSTOOHELLO, no statements flagged.
IGD01008I ALLOCATION SET TO SCTEMPD M0610
IGD01010I ALLOCATION SET TO SGTEMPD STORAGE GROUP
IGD01008I ALLOCATION SET TO SCTEMPD M0610
IGD01010I ALLOCATION SET TO SGTEMPD STORAGE GROUP
IGD01008I ALLOCATION SET TO SCTEMPD M0610
IGD01010I ALLOCATION SET TO SGTEMPD STORAGE GROUP
IGD01008I ALLOCATION SET TO SCTEMPD M0610
IGD01010I ALLOCATION SET TO SGTEMPD STORAGE GROUP
TstHelloJ main is executing!
TstHelloJ has created TstooHello object
COBOL program TSTOOHELLO entered.
Hello World, from Java!
COBOL program TSTOOHELLO returned from Java.
USERID:/a/userid/myjava: >
22
Cobol and Java
3.5. The generated TstooHello.java source
From the TstooHello.cbl program cob2 has generated the TstooHello.java source, which is then processed
by the java compiler.
// PP 5655-S71 IBM Enterprise COBOL for z/OS 4.2.0
//
// Generated Java class definition for COBOL class ooHello.TstooHello
//
// Date generated: 10/31/2014
// Time generated: 10:59:53
//
//
** Do not edit or modify this file!
**
//
** It is (and must be) regenerated whenever the **
//
** COBOL class is compiled.
**
//
package ooHello;
public class TstooHello
extends java.lang.Object {
public native void CallHelloJ();
private native static void _classInit();
static {
System.loadLibrary("ooHello_TstooHello");
ooHello.TstooHello._classInit();
}
}
Note the following
• package statement ooHello has been generated
• loadLibrary name "ooHello_TstooHello"
• CallHelloJ Java class execution
23
Cobol and Java
3.6. Possible causes of errors.
Unresolved references at link time.
• Check out the PATH variables are correct.
• Check out libjvm.x and igzcjava.x exist.
• Check out the consistency between the package name, the package foder name and the script
Errors at execution time.
• JVM initialization errors, Xms or Xmx too small. Adjust these values in the COBJVMINITOPTIONS
• Application noXPLINK attempts to call an XPLink class. Check out the _CEE_RUN_OPTS variable.
• Exception in main thread. Unresolved link. Check out the structure of the application, the -D variable
passed to java
• Exception in main thread. Load error. Check out the structure of the application, the -D variable passed
to java
24
Cobol and Java
4. The oosample example
In this section we won't focus on the various ways to prepare and execute a mixed Cobol and Java application but we'll pay more attention to the structure of such an application.
Requirements
• The IBM Cobol compiler at level V4 or higher
• User has access to the USS
The oosample application is installed with the cobol compiler, usually in the usr/lpp/cobol/demo/oosample
folder.
The JNI copybook is needed. It is usually found in the usr/lpp/cobol/include folder
In that section it is assumed the cobol and java sources have been copied to /a/userid/myjava private folder.
The sources can also be copied form the next sections.
25
Cobol and Java
4.1. The structure of the application
The oosample application is made of these sources:
• TestAccounts.cbl main cobol (recursive)
• Account.cbl oo cobol routine contains methods createAccount, init, getBalance, credit, debit and print
• CheckingAccount.cbl oo cobol routine contains methods createCheckingAccount(2), processCheck
and print
• Check.java java class contains methods Check, getAmount and getPayee
Here's how the application flows. Main program TestAccounts
• Invokes Account program to create an instance of the Account object (anAccount)
• Invokes methods credit and print of the new Account object anAccount
• Invokes CheckingAccount program to create an instance of the CheckingAccount object (aCheckingAccount)
• Invokes Check class to create an instance of the Check object (aCheck)
• Invokes methods processCheck and print of the new aCheckingAccount object
• Invokes print of the object anAccount
26
Cobol and Java
4.2. The Cobol main program TestAccounts.cbl
cbl dll,thread,pgmname(longmixed)
Identification division.
Program-id. "TestAccounts" recursive.
Environment division.
Configuration section.
Repository.
Class Account
is "Account"
Class CheckingAccount is "CheckingAccount"
Class Check
is "Check".
Data Division.
Local-storage section.
01 anAccount
usage object reference Account.
01 aCheckingAccount usage object reference CheckingAccount.
01 aCheck
usage object reference Check.
01 payee
usage object reference Account.
Procedure division.
Test-Account-section.
Display "Test Account class"
Invoke Account "createAccount"
using by value 123456
returning anAccount
Invoke anAccount "credit" using by value 500
Invoke anAccount "print"
Display space
Display "Test CheckingAccount class"
Invoke CheckingAccount "createCheckingAccount"
using by value 777777 300
returning aCheckingAccount
Set payee to anAccount
Invoke Check New
using by value aCheckingAccount, payee, 125
returning aCheck
Invoke aCheckingAccount "processCheck"
using by value aCheck
Invoke aCheckingAccount "print"
Invoke anAccount "print"
Stop Run.
End program "TestAccounts".
Note
• Program TestAccount has a Program-id recursive whereas the other programs have a Class-id.
• The Repository paragraph defines a class for each of the objects in this application.
• The local-storage section specifies storage for each object instance in the application.
• Program uses the special 'invoke' statement to execute java based routines.
27
Cobol and Java
28
Cobol and Java
4.3. The Cobol program Account.cbl
We first give the Account.cbl source then the java source that cob2 generates.
cbl dll,thread,pgmname(longmixed),lib
Identification Division.
Class-id. Account inherits Base.
Environment Division.
Configuration section.
Repository.
Class Base is "java.lang.Object"
Class Account is "Account".
Identification division.
Factory.
Data division.
Working-storage section.
01 NumberOfAccounts pic 9(6) value zero.
Procedure Division.
Identification Division.
Method-id. "createAccount".
Data division.
Linkage section.
01 inAccountNumber pic S9(6) binary.
01 outAccount object reference Account.
Copy JNI.
Procedure Division using by value inAccountNumber
returning outAccount.
Set address of JNIEnv to JNIEnvPtr
Set address of JNINativeInterface to JNIEnv
Invoke Account New returning outAccount
Invoke outAccount "init" using by value inAccountNumber
Add 1 to NumberOfAccounts.
End method "createAccount".
End Factory.
Identification division.
Object.
Data division.
Working-storage section.
01 AccountNumber pic 9(6).
01 AccountBalance pic S9(9) value zero.
Procedure Division.
Identification Division.
Method-id. "init".
Data division.
Linkage section.
01 inAccountNumber pic S9(9) binary.
Procedure Division using by value inAccountNumber.
29
Cobol and Java
Move inAccountNumber to AccountNumber.
End method "init".
Identification Division.
Method-id. "getBalance".
Data division.
Linkage section.
01 outBalance pic S9(9) binary.
Procedure Division returning outBalance.
Move AccountBalance to outBalance.
End method "getBalance".
Identification Division.
Method-id. "credit".
Data division.
Linkage section.
01 inCredit
pic S9(9) binary.
Procedure Division using by value inCredit.
Add inCredit to AccountBalance.
End method "credit".
Identification Division.
Method-id. "debit".
Data division.
Linkage section.
01 inDebit
pic S9(9) binary.
Procedure Division using by value inDebit.
Subtract inDebit from AccountBalance.
End method "debit".
Identification Division.
Method-id. "print".
Data division.
Local-storage section.
01 PrintableAccountNumber pic ZZZZZZ999999.
01 PrintableAccountBalance pic $$$$,$$$,$$9CR.
Procedure Division.
Move AccountNumber to PrintableAccountNumber
Move AccountBalance to PrintableAccountBalance
Display " Account: " PrintableAccountNumber
Display " Balance: " PrintableAccountBalance.
End method "print".
End Object.
End class Account.
Account.java
// PP 5655-S71 IBM Enterprise COBOL for z/OS
//
30
4.2.0
Cobol and Java
// Generated Java class definition for COBOL class Account
//
// Date generated: 11/04/2014
// Time generated: 09:55:15
//
//
** Do not edit or modify this file!
**
//
** It is (and must be) regenerated whenever the **
//
** COBOL class is compiled.
**
//
public class Account
extends java.lang.Object {
public native static Account createAccount(
int INACCOUNTNUMBER);
public native void init(
int INACCOUNTNUMBER);
public native int getBalance();
public native void credit(
int INCREDIT);
public native void debit(
int INDEBIT);
public native void print();
private native static void _classInit();
private java.nio.ByteBuffer Account_instanceData;
private native void _instanceDataInit();
public Account(){
Account_instanceData=java.nio.ByteBuffer.allocateDirect(17);
_instanceDataInit();
}
static {
System.loadLibrary("Account");
Account._classInit();
}
}
Note
• The Class-id inherits class Base
• The Repository paragraph links Base class to 'java.lang.Object', which is the root of the class hierarchy
in Java. It also specifies a class under the same name as the Cobol program so that the cob2 utility
generates a Java program under that name.
• The Account program begins with a Factory paragraph that contains a 'createAccount' method. This
method interfaces with the JVM so the JNI copybook is required.
• The Account program then defines the Account object and in the object a number of methods: init,
getBalance, credit, debint and print.
• The generated java source contains the same elements as the cobol program.
31
Cobol and Java
4.4. The Cobol program CheckingAccount.cbl
We first give the cobol source then the java source that cob2 generates.
cbl dll,thread,pgmname(longmixed),lib
Identification Division.
Class-id. CheckingAccount inherits Account.
Environment Division.
Configuration section.
Repository.
Class CheckingAccount is "CheckingAccount"
Class Check
is "Check"
Class Account
is "Account".
Identification division.
Factory.
Data division.
Working-storage section.
01 NumberOfCheckingAccounts pic 9(6) value zero.
Procedure Division.
Identification Division.
Method-id. "createCheckingAccount".
Data division.
Linkage section.
01 inAccountNumber pic S9(6) binary.
01 outCheckingAccount object reference CheckingAccount.
Copy JNI.
Procedure Division using by value inAccountNumber
returning outCheckingAccount.
Set address of JNIEnv to JNIEnvPtr
Set address of JNINativeInterface to JNIEnv
Invoke CheckingAccount New returning outCheckingAccount
Invoke outCheckingAccount "init"
using by value inAccountNumber
Add 1 to NumberOfCheckingAccounts.
End method "createCheckingAccount".
Identification Division.
Method-id. "createCheckingAccount".
Data division.
Linkage section.
01 inAccountNumber pic S9(6) binary.
01 inInitialBalance pic S9(9) binary.
01 outCheckingAccount object reference CheckingAccount.
Copy JNI.
Procedure Division using by value inAccountNumber
inInitialBalance
returning outCheckingAccount.
Set address of JNIEnv to JNIEnvPtr
Set address of JNINativeInterface to JNIEnv
32
Cobol and Java
Invoke CheckingAccount New returning outCheckingAccount
Invoke outCheckingAccount "init"
using by value inAccountNumber
Invoke outCheckingAccount "credit"
using by value inInitialBalance
Add 1 to NumberOfCheckingAccounts.
End method "createCheckingAccount".
End Factory.
Identification division.
Object.
Data division.
Working-storage section.
01 CheckFee pic S9(9) value 1.
Procedure Division.
Identification Division.
Method-id. "processCheck".
Data division.
Local-storage section.
01 amount pic S9(9) binary.
01 payee usage object reference Account.
Linkage section.
01 aCheck usage object reference Check.
Procedure Division using by value aCheck.
Invoke aCheck "getAmount" returning amount
Invoke aCheck "getPayee" returning payee
Invoke payee "credit" using by value amount
Add checkFee to amount
Invoke self
"debit" using by value amount.
End method "processCheck".
Identification Division.
Method-id. "print".
Data division.
Local-storage section.
01 printableFee pic $$,$$$,$$9.
Procedure Division.
Invoke super "print"
Move CheckFee to printableFee
Display " Check fee: " printableFee.
End method "print".
End Object.
End class CheckingAccount.
The CheckingAccount.java source
// PP 5655-S71 IBM Enterprise COBOL for z/OS 4.2.0
//
// Generated Java class definition for COBOL class CheckingAccount
//
33
Cobol and Java
// Date generated: 11/04/2014
// Time generated: 09:55:16
//
//
** Do not edit or modify this file!
**
//
** It is (and must be) regenerated whenever the **
//
** COBOL class is compiled.
**
//
public class CheckingAccount
extends Account {
public native static CheckingAccount createCheckingAccount(
int INACCOUNTNUMBER);
public native static CheckingAccount createCheckingAccount(
int INACCOUNTNUMBER,
int ININITIALBALANCE);
public native void processCheck(
Check ACHECK);
public native void print();
private native static void _classInit();
private java.nio.ByteBuffer CheckingAccount_instanceData;
private native void _instanceDataInit();
public CheckingAccount(){
CheckingAccount_instanceData=java.nio.ByteBuffer.allocateDirect(9);
_instanceDataInit();
}
static {
System.loadLibrary("CheckingAccount");
CheckingAccount._classInit();
}
}
Note
• The remarks about the Account program also apply to the CheckingAccount program.
• One difference though, is program ChekingAccount inherits the Account class, not Base.
34
Cobol and Java
4.5. The Check java program
public class Check {
private CheckingAccount payer;
private Account payee;
private int amount;
public Check(CheckingAccount inPayer, Account inPayee, int inAmount) {
payer=inPayer;
payee=inPayee;
amount=inAmount;
}
public int getAmount() {
return amount;
}
public Account getPayee() {
return payee;
}
}
35
Cobol and Java
4.6. The oosample.bat script file
Create the oosample.bat script file as the below one right in /a/userid/myjava folder. Note the cob2 bdll commands must be single line commands. In the below listings the cob -bdll commnands have been
segmented in two lines for an easier reading.
#
# Script file for the sample OO COBOL and Java application
# ----------------------------------------------------------------# The oosample application is made of these sources:
#
TestAccounts.cbl
main cobol
(recursive)
#
Account.cbl
oo cobol
#
CheckingAccount.cbl
oo cobol
#
Check.java java class
# ----------------------------------------------------------------# export options are for the execution of the application in Step 7
# ----------------------------------------------------------------# JAVA_HOME is set in the users's .profile
#
JAVASIDEDECKPATH=${JAVA_HOME}/bin/classic
COBOLSIDEDECKPATH=/sys/cobol/V5R1M0/usr/lpp/cobol/lib
COBOLCOPYPATH=/sys/cobol/V5R1M0/usr/lpp/cobol/include
export COBJVMINITOPTIONS="-Xms1200000 -Xmx1200000 -Xverbosegclog:oosamplelogc.lst"
export _CEE_RUNOPTS="XPLINK(ON)"
#
# Compile TestAccounts.cbl into TestAccounts.o (cob2 -o)
# Compile Links TestAccounts.o
(cob2 -bdll)
# Report TestAccounts.blst
#
echo '***'
echo '*** Step 1 - Compiling and linking TestAccounts cobol program'
echo '***'
cob2 -c -I${COBOLCOPYPATH} TestAccounts.cbl >TestAccounts.blst
cob2 -bdll -o libTestAccounts.so TestAccounts.o ${JAVASIDEDECKPATH}/libjvm.x
${COBOLSIDEDECKPATH}/igzcjava.x >TestAccounts.llst
#
# Compile Account.cbl into Account.o (cob2 -o)
# Compile Links Account.o
(cob2 -bdll)
# Report Account.blst
#
echo '***'
echo '*** Step 2 -Compiling and linking Account cobol program'
echo '***'
cob2 -c -bdll -I${COBOLCOPYPATH} Account.cbl
cob2 -o libAccount.so -bdll Account.o ${JAVASIDEDECKPATH}/libjvm.x
${COBOLSIDEDECKPATH}/igzcjava.x >Account.blst
#
# Compile CheckingAccount.cbl no link (cob2 -c)
# Compile CheckingAccount.o
(cob2 -bdll)
# Report CheckingAccount.blst
#
echo '***'
36
Cobol and Java
echo '*** Step 3 -Compiling and linking CheckingAccount cobol program'
echo '***'
cob2 -c -bdll -I${COBOLCOPYPATH} CheckingAccount.cbl
cob2 -o libCheckingAccount.so -bdll CheckingAccount.o
${JAVASIDEDECKPATH}/libjvm.x ${COBOLSIDEDECKPATH}/igzcjava.x >Account.blst
#
# build Account class
#
echo '***'
echo '*** Step 4 - Compiling Account
java program'
echo '***
Compiling CheckingAccount java program'
echo '***
Compiling Check
java program'
echo '***'
javac Account.java
javac CheckingAccount.java
javac Check.java
#
# Execute application
#
echo '***'
echo '*** Step 5 - Execute TstAccounts application'
echo '***'
./libTestAccounts.so
##
### End
Note
• The JAVASIDEDECKPATH, COBOLSIDEDECKPATH and COBOLCOPYPATH variables specify
the location of the JAVA and IBM material. The JNI copybook must be available in the cobol/include
folder.
• From the cobol programs 'libname.so' files are created. The naming convention is that the resulting
module must be prefixed with 'lib'.
• The last line of the script executes libTestAccounts.so, the top module of the oosample application.
37
Cobol and Java
4.7. Execute the script
Type oosample.bat and press Enter.
The executables are built and the application executes if no error was encountered. Below is an example
of the messages that are produced by the script.
....
***
*** Step 3 -Compiling and linking CheckingAccount cobol program
***
PP 5655-S71 IBM Enterprise COBOL for z/OS 4.2.0 in progress ...
End of compilation 1, class CHECKINGACCOUNT, no statements flagged.
IGD01008I ALLOCATION SET TO SCTEMPD M0610
IGD01010I ALLOCATION SET TO SGTEMPD STORAGE GROUP
IGD01008I ALLOCATION SET TO SCTEMPD M0610
IGD01010I ALLOCATION SET TO SGTEMPD STORAGE GROUP
***
*** Step 4 ***
***
***
***
*** Step 5 ***
Test Account
Account:
Balance:
Compiling Account
java program
Compiling CheckingAccount java program
Compiling Check
java program
Execute TstAccounts application
class
123456
$500
Test CheckingAccount class
Account:
777777
Balance:
$174
Check fee:
$1
Account:
123456
Balance:
$625
38
Chapter 2. Cobol, XML and XSD
This chapter presents programs based on the examples in the 'XML Processing on Z/OS' manual and
demonstrate the usage of XML oriented cobol statements with validation by a XML Schema definition
(XSD file) using the XML System Services (XMLSS) as well as querying the XML System Services.
In the below sections we assume the user has allocated a PDS named userid.XML.SOURCE with a
DCB=(LREC=80,RECFM=FB,BLKSIZE=4160)
It is assumed also user created a folder named 'xml' in his USS environment.
39
Cobol, XML and XSD
1. The XMLCOB1 example
References
The 'XML Processing in Z/OS manual', chapter 5 How to generate XML, about the XML GENERATE
statement
The 'XML Processing in Z/OS manual', chapter 8 How to parse XML, about the XML PARSE statement
using System Services
The 'XML Processing in Z/OS manual', chapter 9 Hints, tips and samples (OSR generation)
Requirements
• User has access to the TSO/E environment and can execute the IBM Cobol compiler at level V4 or higher
• The XML toolkit is available in the USS.
• User can start a TSO/E session and has access to the USS
40
Cobol, XML and XSD
1.1. The Cobol program
Program XMLCOB1 is not an IBM source. It is supplied to demonstrate how XML generation and XML
parsing can be set up in one single program. The goal here is to show that the XML that Cobol generates
is well formed and parses with no error.
Program XMLCOB1 operates as follows
• The harcoded records that are used in conjunction with copybook TSTCOPY to produce the XML are
printed.
• The XML statements are then generated in a continuous buffer that is printed.
• The XML statements are copied one per line to the allocated output.
• The XML buffer is parsed back and its elements are printed one per line.
For the simplicity of the demonstration the program handles a small amount of data so that only one 32K
buffer is needed to hold the XML output.
CBL XMLPARSE(XMLSS)
IDENTIFICATION DIVISION.
PROGRAM-ID. XMLCOB1.
*AUTHOR.
PATRICE COTTE.
DATE-COMPILED. 24/11/14
.
ENVIRONMENT DIVISION.
CONFIGURATION SECTION.
SPECIAL-NAMES.
ALPHABET HOST IS EBCDIC
C01 IS NEW-PAGE
* Define the set of supported characters in both the EBCDIC
* and XML english tables.
CLASS ebcdic-english-and-xml IS
SPACE '.' '<' '(' '+' '|' '&' '!' '$' '*' ')' ';' '-' '/'
'a' thru 'i'
'j' thru 'r' '~'
's' thru 'z' '¬' '[' ']' '{'
'A' thru 'I' '}'
'J' thru 'R' '\'
'S' thru 'Z'
'0' thru '9'
x'05' x'0D' x'15' x'25'
* Use this declaration if using VALIDATING WITH FILE clause
XML-SCHEMA MYSCHEMA IS TSTXSD
.
OBJECT-COMPUTER.
IBM-370-Z145.
* SOURCE-COMPUTER. IBM DEBUGGING MODE.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT MYPRINT ASSIGN TO SYSPRINT
FILE STATUS IS MYPRINT-STATUS.
SELECT TSTXML ASSIGN TO TSTXML
41
Cobol, XML and XSD
ORGANIZATION IS SEQUENTIAL
FILE STATUS IS TSTXML-STATUS.
SELECT TSTXSD ASSIGN TO TSTXSD
ORGANIZATION IS SEQUENTIAL
FILE STATUS IS TSTXSD-STATUS.
DATA DIVISION.
FILE SECTION.
FD MYPRINT
BLOCK CONTAINS 0 TO 3990 CHARACTERS
RECORD VARYING IN SIZE
FROM 1 TO 133 CHARACTERS
DEPENDING ON REC-SIZE
LABEL RECORD IS STANDARD
DATA RECORD IS FILEREC
RECORDING MODE IS V
CODE-SET IS HOST.
01 FILEREC.
05 ASA-FILEREC PIC X.
05 DATA-FILEREC PIC X(132).
FD
01
FD
01
TSTXML
BLOCK CONTAINS 0 TO 4160 CHARACTERS
RECORDING MODE F
DATA RECORD IS XMLREC.
XMLREC
PIC X(80).
TSTXSD
BLOCK CONTAINS 0 TO 4160 CHARACTERS
RECORDING MODE F
DATA RECORD IS TSTXSD-REC.
TSTXSD-REC
PIC X(80).
/
WORKING-STORAGE SECTION.
77 MYPRINT-STATUS
88 OPEN-OK
PIC
9(2)
VALUE 0.
VALUE 0.
*
77
77
77
TSTXSD-STATUS
TSTXSD-EOF
88 TSTXSD-EOF-HIT
88 TSTXSD-NO-EOF
TSTXSD-COUNT
PIC 9(2) VALUE 0.
PIC X.
VALUE 'Y'.
VALUE 'N'.
PIC 9(4) VALUE 0.
TSTXML-STATUS
XMLREC-SIZE
XMLLEN
XMLERR-OFFSET
XMLCOUNT
XML-PRT-COUNT
XML-CODEPAGE
XML-CHAR-COUNT
XMLPOS
TAGSTATE
QUOTESTATE
PIC 9(2)
PIC 9(8)
PIC 9(4)
PIC 9(4)
PIC S9(9)
PIC 9(4)
PIC 9(4)
PIC 9(5)
PIC 9(5)
PIC 9
PIC 9
*
77
77
77
77
77
77
77
77
77
77
77
*
42
VALUE 0.
COMP VALUE 80.
VALUE 0.
VALUE 0.
COMP-4 VALUE 0.
VALUE 0.
VALUE 1140.
COMP-5 VALUE 0.
COMP-5 VALUE 0.
COMP-5 VALUE 0.
COMP-5 VALUE 0.
Cobol, XML and XSD
77
01
WS-MSGINFO-INDEX
PIC 9(5) COMP.
WS-MSGINFO-BLOCK.
03 WS-MSGINFO-BLOCK-ENTRY OCCURS 10 TIMES
INDEXED BY WS-MSGINFO-I.
05 WS-MSGINFO-ASA
PIC X.
05 WS-MSGINFO-DATA PIC X(80).
*
77
77
77
77
77
77
77
*
77
77
77
77
77
77
77
77
77
77
77
77
77
/
*
**
*
01
01
01
*
*
*
PAGE-COUNT
PIC 9(9) COMP VALUE 0.
LPERPAGE-COUNT
PIC 9(5) COMP VALUE 0.
MAX-PER-PAGE
PIC 9(5) COMP VALUE 60 .
PAGE-OFFSET
PIC 9(5) COMP VALUE 110.
DATE-OFFSET
PIC 9(5) COMP VALUE 105.
DATALEN
PIC 9(5) COMP VALUE 100.
REC-SIZE
PIC 9(8) COMP VALUE 133.
ZCOUNT:Print field, Pcount:Page count, LCount:Loop count
WS-ZCOUNT
PIC ZZZZZ9.
WS-PCOUNT
PIC 9(4) COMP VALUE 0.
WS-LCOUNT
PIC 9(4) COMP VALUE 0.
WS-POS
PIC 9(4) COMP VALUE 0.
WS-NONZERO-POS
PIC 9(9) COMP VALUE 0.
WS-NONBLANK-POS
PIC 9(9) COMP VALUE 0.
WS-LEN
PIC 9(9) COMP VALUE 0.
WS-COUNT
PIC 9(9)
VALUE 0.
SUBT1
PIC 9(4) COMP VALUE 0.
WS-FSTATUS
PIC 9(2) VALUE 0.
WS-FNAME
PIC X(8).
WS-SYSID
PIC X(4).
WS-PRINT
PIC X
VALUE SPACES.
Date/Time areas.
WS-DATETIME-HEADER
WS-DATE-YYYYMMDD.
10 WS-DATE-CENTURY
10 WS-DATE-YYMMDD.
15 WS-DATE-YEAR
15 WS-DATE-MONTH
15 WS-DATE-DAY
WS-DAY-YYYYDDD.
10 WS-DAY-CENTURY
10 WS-DAY-YYDDD.
15 WS-DAY-YEAR
15 WS-DAY-DAY
PIC
X(40)
VALUE SPACES.
PIC
9(02)
VALUE ZERO.
PIC
PIC
PIC
9(02)
9(02)
9(02)
VALUE ZERO.
VALUE ZERO.
VALUE ZERO.
PIC
9(02)
VALUE ZERO.
PIC
PIC
9(02)
9(03)
VALUE ZERO.
VALUE ZERO.
PIC
9
VALUE 1.
1:Monday to 7:Sunday.
01
01
WS-DAY-OF-WEEK
WS-TIME.
10 WS-TIME-HH
10 WS-TIME-MM
10 WS-TIME-SS
10 WS-TIME-DD
PIC
PIC
PIC
PIC
/
43
9(02)
9(02)
9(02)
9(02)
VALUE
VALUE
VALUE
VALUE
ZERO.
ZERO.
ZERO.
ZERO.
Cobol, XML and XSD
*
* ** Constants
*
77 SCALE1
PIC X(49) VALUE
' *----+----1----+----2----+----3----+----4----+-'.
77 SCALE2
PIC X(54) VALUE
'---5----+----6----+----7----+----8----+----9----+----0'.
/
* ** Data record Cobol layout.
01 test-list.
05 test-entry occurs 99 times
depending on XMLCOUNT.
Copy TSTCOPY.
*
*
*
*
*
*
*
*
*
*
*
** XML area and fields.
The following elements are ignored when the XML definitions
are generated:
- pointer fields
- slack bytes resulting from synchronize
- redefinitions
- filler
The generated area must be 5 to 10 times the size of the input.
77
77
01
generated-length
pic s9(4) comp.
string-length-pointer pic s9(9) binary value 1.
generated-xml-text pic x(32760).
01
01
01
xml-entry-number
pic
XML-document-length
pic
XML-doclen-alpha redefines
pic
XML-element
pic
01
s9(4) comp.
999
comp.
XML-document-length
9(3).
x(132).
* Map the XML-CODE special register.
01 XMLCODE.
02 XMLRTN
PIC 9(8).
02 XMLRSN
PIC 9(8).
01 XMLCODE-BIN
PIC 9(9) COMP-5.
01 XMLRTNRSN-BIN redefines XMLCODE-BIN.
02 XMLRTN-BIN
PIC 9(4) COMP-5.
02 XMLRSN-BIN
PIC 9(4) COMP-5.
01 XMLRTN-MSG
PIC X(30).
01 XMLRSN-MSG
PIC X(60).
* ** SCHEMA area. When using the VALIDATING clause without
*
the FILE parameter the SCHEMA must be read into this area
*
prior to the parsing with validation.
01 SCHEMA-AREA
PIC X(32760).
LINKAGE SECTION.
The following system areas start at address 0 and do
*
44
Cobol, XML and XSD
*
01
01
01
not require a USING in the PROC DIV statement.
PSA.
05 FILLER
PIC X(16).
05 FLCCVT
POINTER.
CVT.
05 FILLER
PIC X(196).
05 CVTSMCA
POINTER.
SMCA.
05 FILLER
PIC X(16).
05 SMCASID
PIC X(4).
/
PROCEDURE DIVISION.
0000-MAINLINE SECTION.
*
* Open the Sysprint and print the header.
*
Open OUTPUT MYPRINT
Perform 9000-PRINT-HEADER
thru 9000-PRINT-HEADER-EXIT
Move MyPrint-Status to WS-FSTATUS
Move 'SYSPRINT' to WS-FNAME
Perform 9100-PRINT-FS-STATUS
thru 9100-PRINT-FS-STATUS-EXIT
IF MyPrint-Status > 0
GOBACK
END-IF
*
* 'Read' and validate the input.
*
Perform 1000-INIT-SECTION Thru 1000-INIT-SECTION-EXIT
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
The COUNT IN clauses appear no longer valid ?
WITH ATTRIBUTES drives the generation of tags such as
<name lastn="lastnName1" firstn="firstnName1">
Without the ATTRIBUTES clause the generation would be like
<name>
<lastn>lastName1</lastn)
<firstn>firstName1</firstn>
</name>
WITH XML-DECLARATION generates the following
<?xml version="1.0" encoding="IBM-1140"?>
WITH NAMESPACE-PREFIX generates this kind of tag:
45
Cobol, XML and XSD
*
<abc:name><abc:lastn>lastnName1</abc:lastn>
*
<abc:firstn>firstnName1</abc:firstn>
* Note, a restrction applies, the namespace must be
*
'http://www.w3.org/2001/XMLSchema'
*
XML GENERATE generated-xml-text
FROM test-list
WITH XML-DECLARATION
*
WITH attributes
*
COUNT IN generated-length
*
NAMESPACE 'http://www.w3.org/2001/XMLSchema'
*
NAMESPACE-PREFIX 'abc'
ON EXCEPTION
PERFORM 9220-PRINT-XML-ERROR
thru 9220-PRINT-XML-ERROR-EXIT
STOP RUN
NOT ON EXCEPTION
PERFORM 9210-PRINT-XML-OK
thru 9210-PRINT-XML-OK-EXIT
END-XML.
* Guess how much XML has been generated.
Perform 8200-GUESS-LENGTH
thru 8200-GUESS-LENGTH-EXIT
Open OUTPUT TSTXML
Perform 9050-PRINT-BLANK-LINE
thru 9050-PRINT-BLANK-LINE-EXIT
Move TstXML-Status to WS-FSTATUS
Move 'TSTXML'
to WS-FNAME
Perform 9100-PRINT-FS-STATUS
thru 9100-PRINT-FS-STATUS-EXIT
IF TstXML-Status
CLOSE MYPRINT
GOBACK
END-IF
> 0
*
Copy the generated text. We copy one tagged entry per line
Move 1 to WS-POS
Move WS-NONZERO-POS to WS-LEN
Move 'Y' to WS-PRINT
Perform 9250-COPY-XML thru 9250-COPY-XML-EXIT
until WS-LEN > 32760
or WS-Print = 'N'
*
Print generated-xml-text, one tagged entry per line
Move 1 to WS-POS
Move 0 to WS-LEN SUBT1
Move 'Y' to WS-PRINT
Perform 9200-PRINT-XML thru 9200-PRINT-XML-EXIT
until WS-LEN > 32760
46
Cobol, XML and XSD
or WS-Print = 'N'
Perform 9800-PRINT-XMLEND-MSG
thru 9800-PRINT-XMLEND-MSG-EXIT
Perform 9050-PRINT-BLANK-LINE
thru 9050-PRINT-BLANK-LINE-EXIT
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
Parse the generated XML text.
-------------------------------------------------------------The following special registers are used by the XML Parsing:
Implicit desc
Notes
XML-EVENT
X(30) value spaces.
Sending item
XML-CODE
S9(9) comp value 0.
Rc or 0.
XML-TEXT
Variable length < 16M Sending item
generated text.
XML-NTEXT
Variable length < 16M Sending item
generated text (National)
Encoding is performed according to the CHAR option.
If using the ENCODING clause it must reference a PIC 9(4)
variable that contains a valid CCSID:
1208
1047
1140, 37
1141,
1142,
1143,
1144,
1145,
1146,
1147,
1148,
1149,
273
277
278
280
284
285
297
500
871
UTF-8(1)
Latin 1 / Open Systems
USA, Canada, . . .
Euro Country Extended Code Page (ECECP)
Austria, Germany ECECP, CECP
Denmark, Norway ECECP, CECP
Finland, Sweden ECECP, CECP
Italy ECECP, CECP
Spain, Latin America (Spanish) ECECP, CECP
UK ECECP, CECP
France ECECP, CECP
International ECECP, CECP
Iceland ECECP, CECP
With VALIDATION clause refers to a FILE entry + SPECIAL NAME
If the FILE parameter is omitted the name is an area name
and the schema must be read into the area prior to the parsing.
-------------------------------------------------------------Perform
thru
Perform
thru
9820-PRINT-STARTXML
9820-PRINT-STARTXML-EXIT
9050-PRINT-BLANK-LINE
9050-PRINT-BLANK-LINE-EXIT
* ** In order to parse back the buffer we need to space
* ** everything that follows the XML text. WS-NONZERO-POS
* ** was computed in the 8200- section.
MOVE SPACES to
generated-xml-text(WS-NONZERO-POS + 1:)
* ** For performance reasons, particularly when the same schema
47
Cobol, XML and XSD
* ** is used to validate several file the schema can be loaded
* ** into core and the PARSE use the VALIDATING with identifier
* ** where identifie is the name of the in-core schema copy.
Perform 8400-Read-Schema
thru 8400-Read-Schema-Exit.
*
XML PARSE generated-xml-text
ENCODING XML-CODEPAGE
VALIDATING WITH FILE MYSCHEMA
VALIDATING WITH SCHEMA-AREA
PROCESSING PROCEDURE XMLEVENT-HANDLER
ON EXCEPTION
PERFORM 9860-PRINT-XMLERROR
thru 9860-PRINT-XMLERROR-EXIT
STOP RUN
NOT ON EXCEPTION
PERFORM 9840-PRINT-XMLEND-OK
thru 9840-PRINT-XMLEND-OK-EXIT
END-XML
Close TSTXML
Close TSTXSD
Close MYPRINT
.
0000-MAINLINE-EXIT.
Goback.
1000-INIT-SECTION.
Initialize test-entry (1)
Compute XMLCOUNT = XMLCOUNT + 1
MOVE 'XYZ00001'
to individual-ID (1)
MOVE 'COTTE'
to lastname (1)
MOVE 'Patrice'
to firstname (1)
MOVE 'DE'
to country-code (1)
MOVE 32767
to redbooks-number (1)
Compute xml-entry-number = xml-entry-number + 1
* In real life we would read data from some file and possibly
* make sure some character fields are acceptable.
PERFORM 1030-XML-CHAR-CHECK thru
1030-XML-CHAR-CHECK-EXIT
Initialize test-entry (2)
Compute XMLCOUNT = XMLCOUNT + 1
MOVE '02A546Z9'
to individual-ID (2)
MOVE 'GARCIA'
to lastname (2)
MOVE 'Andy'
to firstname (2)
MOVE 'DK'
to country-code (2)
MOVE 1
to redbooks-number (2)
Compute xml-entry-number = xml-entry-number + 1
* Make sure the records contain data.
PERFORM 1030-XML-CHAR-CHECK thru
48
Cobol, XML and XSD
1030-XML-CHAR-CHECK-EXIT
* Print a blank line (or skip if page is full).
IF LPERPAGE-COUNT < MAX-PER-PAGE
PERFORM 9050-PRINT-BLANK-LINE thru
9050-PRINT-BLANK-LINE-EXIT
END-IF
.
1000-INIT-SECTION-EXIT.
Exit.
/
*
* ** Check out compatibility of a name field with the
* ** EBCDIC/XML character table.
* ** XMLCOUNT has the rank of the current record.
*
1030-XML-CHAR-CHECK.
IF LPERPAGE-COUNT + 1 >= MAX-PER-PAGE
MOVE 1 to ASA-FILEREC
LPERPAGE-COUNT
PERFORM 9000-PRINT-HEADER THRU 9000-PRINT-HEADER-EXIT
ELSE
MOVE SPACE to ASA-FILEREC
END-IF
MOVE SPACES to DATA-FILEREC
MOVE XMLCOUNT to XML-PRT-COUNT
IF individual-name (XMLCOUNT) NOT ebcdic-english-and-xml
STRING 'Field individual-name (' XML-PRT-COUNT ') '
individual-name(XMLCOUNT) 'is NOT compatible '
'with the EBCDIC/XML table.'
delimited by size
into DATA-FILEREC
ELSE
STRING 'Field individual-name (' XML-PRT-COUNT ') '
individual-name(XMLCOUNT) 'is compatible with '
'the EBCDIC/XML table.'
delimited by size
into DATA-FILEREC
END-IF
WRITE FILEREC
COMPUTE LPERPAGE-COUNT = LPERPAGE-COUNT + 1.
1030-XML-CHAR-CHECK-EXIT.
EXIT.
/
*****************************************************************
*
Adjust routines 2000-XML-ADJUST
*
*
2010-XML-ADJUST
*
*****************************************************************
2000-XML-ADJUST.
49
Cobol, XML and XSD
Move 0 to tagstate
quotestate
Perform varying XMLPOS from 1 by 1
until XMLPOS > XML-CHAR-COUNT
if XMLREC(XMLPOS:1) = '<'
move 1 to tagstate
end-if
if tagstate = 1
if XMLREC(XMLPOS:1) = '"'
move 1 to quotestate
else
move 0 to quotestate
end-if
end-if
if tagstate = 1 and quotestate = 0
Evaluate true
When XMLREC(XMLPOS:1) = '-'
move '_' to XMLREC(XMLPOS:1)
When XMLREC(XMLPOS:1) = '>'
move 0 to tagstate
When other
move function lower-case (XMLREC (XMLPOS:1))
to XMLREC(XMLPOS:1)
End-evaluate
end-if
End-perform.
2000-XML-ADJUST-EXIT.
Exit.
2010-XML-ADJUST.
Move 0 to tagstate
quotestate
Perform varying XMLPOS from 1 by 1
until XMLPOS > XML-CHAR-COUNT
if DATA-FILEREC(XMLPOS:1) = '<'
move 1 to tagstate
end-if
if tagstate = 1
if DATA-FILEREC(XMLPOS:1) = '"'
move 1 to quotestate
else
move 0 to quotestate
end-if
end-if
50
Cobol, XML and XSD
if tagstate = 1 and quotestate = 0
Evaluate true
When DATA-FILEREC(XMLPOS:1) = '-'
move '_' to DATA-FILEREC(XMLPOS:1)
When DATA-FILEREC(XMLPOS:1) = '>'
move 0 to tagstate
When other
move function lower-case (DATA-FILEREC (XMLPOS:1))
to DATA-FILEREC(XMLPOS:1)
End-evaluate
end-if
End-perform.
2010-XML-ADJUST-EXIT.
EXIT.
/
*****************************************************************
*
Print routines 9000-PRINT-HEADER
*
*
9050-PRINT-BLANK-LINE
*
*
9100-PRINT-FS-STATUS
*
*
9200-PRINT-XML
*
*
9210-PRINT-XML-OK
*
*
9220-PRINT-XML-ERROR
*
*
9800-PRINT-XMLEND-MSG
*
*
9820-PRINT-STARTXML
*
*
9840-PRINT-XMLEND-OK
*
*
9860-PRINT-XML-ERROR
*
*****************************************************************
9000-PRINT-HEADER.
PERFORM 8000-DATE-TIME THRU 8000-DATE-TIME-EXIT
PERFORM 8100-GET-SYSID THRU 8100-GET-SYSID-EXIT
MOVE SPACES
to FILEREC
COMPUTE PAGE-COUNT = PAGE-COUNT + 1
MOVE
PAGE-COUNT to WS-PCOUNT
MOVE
1
to ASA-FILEREC
LPERPAGE-COUNT
MOVE 'XMLCOB1 Utility v1r0' to DATA-FILEREC
MOVE 'Page'
to DATA-FILEREC (PAGE-OFFSET:4)
MOVE WS-PCOUNT
to DATA-FILEREC (PAGE-OFFSET + 6:6)
WRITE FILEREC
MOVE
MOVE
MOVE
MOVE
MOVE
MOVE
MOVE
MOVE
MOVE
MOVE
MOVE
SPACES
to FILEREC
'System ' to DATA-FILEREC
WS-SYSID to DATA-FILEREC (8:4)
'20'
to DATA-FILEREC (DATE-OFFSET:2)
WS-DATE-YEAR to DATA-FILEREC(DATE-OFFSET
'-'
to DATA-FILEREC(DATE-OFFSET
WS-DATE-MONTH to DATA-FILEREC(DATE-OFFSET
'-'
to DATA-FILEREC(DATE-OFFSET
WS-DATE-DAY
to DATA-FILEREC(DATE-OFFSET
SPACES
to DATA-FILEREC(DATE-OFFSET
WS-TIME-HH
to DATA-FILEREC(DATE-OFFSET
51
+
+
+
+
+
+
+
2:2)
4:1)
5:2)
7:1)
8:2)
10:2)
12:2)
Cobol, XML and XSD
MOVE ':'
to DATA-FILEREC(DATE-OFFSET + 14:1)
MOVE WS-TIME-MM
to DATA-FILEREC(DATE-OFFSET + 15:2)
WRITE FILEREC
COMPUTE LPERPAGE-COUNT = LPERPAGE-COUNT + 1
Perform 9050-PRINT-BLANK-LINE
thru 9050-PRINT-BLANK-LINE-EXIT
.
9000-PRINT-HEADER-EXIT.
EXIT.
9050-PRINT-BLANK-LINE.
If LPERPAGE-COUNT + 1 >= MAX-PER-PAGE
EXIT
End-IF
MOVE SPACES to FILEREC
WRITE FILEREC
COMPUTE LPERPAGE-COUNT = LPERPAGE-COUNT + 1
.
9050-PRINT-BLANK-LINE-EXIT.
EXIT.
9100-PRINT-FS-STATUS.
COMPUTE WS-COUNT = xml-entry-number + 1
SET
WS-MSGINFO-I to 1
MOVE 1 to WS-MSGINFO-INDEX
IF WS-FSTATUS
not = 00
MOVE SPACES to WS-MSGINFO-DATA(WS-MSGINFO-I)
STRING 'XMLCOB1E *** ' WS-FNAME
' File error, file-status: '
WS-FSTATUS delimited by size
INTO WS-MSGINFO-DATA(WS-MSGINFO-I)
COMPUTE WS-MSGINFO-INDEX = WS-MSGINFO-INDEX + 1
SET WS-MSGINFO-I to WS-MSGINFO-INDEX
END-IF
*
*
*
MOVE SPACES to FILEREC
EVALUATE TRUE
Successfull completion
.................0----+----1----+----2----+----3----+----4
WHEN WS-FSTATUS = 00
MOVE SPACES to WS-MSGINFO-DATA(WS-MSGINFO-I)
STRING 'XMLCOB1I *** File '
DELIMITED by SIZE
WS-Fname
DELIMITED by SIZE
' successfully opened '
DELIMITED by SIZE
into WS-MSGINFO-DATA(WS-MSGINFO-I)
MOVE 1 to WS-MSGINFO-INDEX
Successfull completion but ...
WHEN WS-FSTATUS = 02
STRING 'XMLCOB1I *** Duplicate key condition '
52
Cobol, XML and XSD
*
'when reading or writing an indexed file.'
DELIMITED by SIZE
into WS-MSGINFO-DATA(WS-MSGINFO-I)
MOVE 1 to WS-MSGINFO-INDEX
WHEN WS-FSTATUS = 04
STRING 'XMLCOB1I *** The record length does not'
' conform to the fixed file format.
'
DELIMITED by SIZE
into WS-MSGINFO-DATA(WS-MSGINFO-I)
MOVE 1 to WS-MSGINFO-INDEX
WHEN WS-FSTATUS = 05
STRING 'XMLCOB1I *** Open successful in I-O or '
'EXTEND mode, file has been created.
'
DELIMITED by SIZE
into WS-MSGINFO-DATA(WS-MSGINFO-I)
MOVE 1 to WS-MSGINFO-INDEX
WHEN WS-FSTATUS = 07
STRING 'XMLCOB1I *** Open for removal or Close '
'no rewind on a non-reel unit.
'
DELIMITED by SIZE
into WS-MSGINFO-DATA(WS-MSGINFO-I)
MOVE 1 to WS-MSGINFO-INDEX
At end conditions
WHEN WS-FSTATUS = 10
STRING 'XMLCOB1I *** At end condition on a Read'
'statement.
'
DELIMITED by SIZE
into WS-MSGINFO-DATA(WS-MSGINFO-I)
MOVE 1 to WS-MSGINFO-INDEX
WHEN WS-FSTATUS = 34
STRING 'XMLCOB1I *** Permanent error condition '
'trying to write beyond the file '
'boundaries.'
DELIMITED by SIZE
into WS-MSGINFO-DATA(WS-MSGINFO-I)
MOVE 1 to WS-MSGINFO-INDEX
WHEN WS-FSTATUS = 35
STRING 'XMLCOB1I *** An Open failed on a missing '
'non optional file.'
DELIMITED by SIZE
into WS-MSGINFO-DATA(WS-MSGINFO-I)
MOVE 1 to WS-MSGINFO-INDEX
WHEN WS-FSTATUS = 37
STRING 'XMLCOB1I *** An Open failed because the '
'open mode is not compatible with the file.'
DELIMITED by SIZE
into WS-MSGINFO-DATA(WS-MSGINFO-I)
MOVE 1 to WS-MSGINFO-INDEX
WHEN WS-FSTATUS = 38
STRING 'XMLCOB1I *** An Open failed because the '
'file has been closed with lock.'
DELIMITED by SIZE
into WS-MSGINFO-DATA(WS-MSGINFO-I)
MOVE 1 to WS-MSGINFO-INDEX
53
Cobol, XML and XSD
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
WHEN WS-FSTATUS = 39
STRING 'XMLCOB1I *** File Definition is not cons'
'sistent with a Fixed file attributes.'
DELIMITED by SIZE
into WS-MSGINFO-DATA(WS-MSGINFO-I)
MOVE 1 to WS-MSGINFO-INDEX
Logic error conditions
WHEN WS-FSTATUS = 41
WHEN WS-FSTATUS = 42
WHEN WS-FSTATUS = 43
WHEN WS-FSTATUS = 44
WHEN WS-FSTATUS = 46
WHEN WS-FSTATUS = 47
WHEN WS-FSTATUS = 48
WHEN WS-FSTATUS = 49
Implement other conditions
WHEN WS-FSTATUS = 90
WHEN WS-FSTATUS = 91
WHEN WS-FSTATUS = 92
WHEN WS-FSTATUS = 93
WHEN WS-FSTATUS = 94
WHEN WS-FSTATUS = 95
WHEN WS-FSTATUS = 96
WHEN WS-FSTATUS = 97
WHEN WS-FSTATUS = 98
STRING 'XMLCOB1E *** File not allocated under'
'the ddname set in SELECT ... ASSIGN ddname.'
DELIMITED by SIZE
into WS-MSGINFO-DATA(WS-MSGINFO-I)
MOVE 1 to WS-MSGINFO-INDEX
WHEN WS-FSTATUS = 99
WHEN OTHER
MOVE SPACES TO FILEREC
END-EVALUATE
IF LPERPAGE-COUNT + WS-MSGINFO-INDEX > MAX-PER-PAGE
MOVE 1 to WS-MSGINFO-ASA(1)
PERFORM 9000-PRINT-HEADER THRU 9000-PRINT-HEADER-EXIT
ELSE
MOVE SPACE to WS-MSGINFO-ASA(1)
END-IF
PERFORM VARYING WS-MSGINFO-I from 1 by 1
Until WS-MSGINFO-I > WS-MSGINFO-INDEX
WRITE FILEREC FROM WS-MSGINFO-BLOCK-ENTRY (WS-MSGINFO-I)
COMPUTE LPERPAGE-COUNT = LPERPAGE-COUNT + 1
END-PERFORM
MOVE SPACES to FILEREC
WRITE FILEREC
COMPUTE LPERPAGE-COUNT = LPERPAGE-COUNT + 1
.
*
* The XML buffer is a continuous string.
54
Cobol, XML and XSD
*
9100-PRINT-FS-STATUS-EXIT.
EXIT.
/
* ** the XML buffer is a continuous buffer. A binary zero
* ** means the end of the XML code has been found.
9200-PRINT-XML.
MOVE SPACES to FILEREC
IF LPERPAGE-COUNT + 1 >= MAX-PER-PAGE
MOVE 1 to ASA-FILEREC
LPERPAGE-COUNT
PERFORM 9000-PRINT-HEADER THRU 9000-PRINT-HEADER-EXIT
ELSE
MOVE SPACE to ASA-FILEREC
END-IF
MOVE generated-xml-text (WS-POS:Length of DATA-FILEREC)
to DATA-FILEREC
MOVE 0 to SUBT1
INSPECT DATA-FILEREC TALLYING SUBT1
FOR CHARACTERS BEFORE INITIAL x'00'
IF SUBT1 < Length of DATA-FILEREC
MOVE 'N' to WS-Print
INSPECT DATA-FILEREC CONVERTING LOW-VALUES TO SPACE
End-If
WRITE FILEREC
COMPUTE WS-LEN = WS-LEN + Length of DATA-FILEREC
COMPUTE WS-POS = WS-POS + Length of DATA-FILEREC
COMPUTE LPERPAGE-COUNT = LPERPAGE-COUNT + 1
.
9200-PRINT-XML-EXIT.
EXIT.
/
* ** the XML GENERATE worked with no error. Print success.
9210-PRINT-XML-OK.
MOVE SPACES to DATA-FILEREC
MOVE 'XMLCOB1I *** XML document was successfully parsed'
to DATA-FILEREC
WRITE FILEREC
COMPUTE LPERPAGE-COUNT = LPERPAGE-COUNT + 1.
9210-PRINT-XML-OK-EXIT.
EXIT.
/
* ** the XML GENERATE failed. Print the error code.
55
Cobol, XML and XSD
9220-PRINT-XML-ERROR.
MOVE SPACES to DATA-FILEREC
MOVE XML-CODE to XMLCODE-BIN
MOVE XMLRTN-BIN to XMLRTN
MOVE XMLRSN-BIN to XMLRSN
STRING 'XMLCOB1I *** XML parsing failed with the XML Code: '
delimited by size
XMLCODE
' RTN='
XMLRTN
' RSN='
XMLRSN
delimited by size
into DATA-FILEREC
WRITE FILEREC
COMPUTE LPERPAGE-COUNT = LPERPAGE-COUNT + 1.
9220-PRINT-XML-ERROR-EXIT.
EXIT.
/
* ** the XML buffer is a continuous buffer. Each expression
* ** is limited by a '>' end tag.A binary zero means the end
* ** of the XML code has been found.
9250-COPY-XML.
MOVE SPACES to XMLREC
* ** locate the end of a tagged expression.
MOVE 0 to SUBT1
INSPECT GENERATED-XML-TEXT (WS-POS: WS-LEN)
TALLYING SUBT1
FOR CHARACTERS BEFORE INITIAL '>'
* ** When found copy to the print buffer, adjust the lrecl
IF SUBT1 > 0
COMPUTE SUBT1 = SUBT1 + 1
MOVE GENERATED-XML-TEXT (WS-POS: SUBT1)
TO XMLREC
COMPUTE XMLREC-SIZE = SUBT1
* ** Perform additional adjustments:
*
- change hyphens into undescore
*
- uppercase element names
MOVE SUBT1 to XML-CHAR-COUNT
PERFORM 2000-XML-ADJUST thru
2000-XML-ADJUST-EXIT
* ** We are now ready to write
WRITE XMLREC
COMPUTE WS-LEN = WS-LEN - SUBT1
COMPUTE WS-POS = WS-POS + SUBT1
ELSE
56
Cobol, XML and XSD
MOVE 'N' to WS-Print
END-IF
.
9250-COPY-XML-EXIT.
EXIT.
/
* ** Print an XML element as parsed by the XML Parser.
9300-PRINT-XMLPARSED.
MOVE SPACES to FILEREC
* ** Honor the LPER value but don't print the header on each
* ** page.
IF LPERPAGE-COUNT + 1 >= MAX-PER-PAGE
MOVE 1 to ASA-FILEREC
LPERPAGE-COUNT
ELSE
MOVE SPACE to ASA-FILEREC
END-IF
MOVE XML-Element (1:Length of DATA-FILEREC)
to DATA-FILEREC
WRITE FILEREC
COMPUTE LPERPAGE-COUNT = LPERPAGE-COUNT + 1
.
9300-PRINT-XMLPARSED-EXIT.
EXIT.
/
9800-PRINT-XMLEND-MSG.
IF LPERPAGE-COUNT + 1 >= MAX-PER-PAGE
MOVE 1 to ASA-FILEREC
LPERPAGE-COUNT
PERFORM 9000-PRINT-HEADER THRU 9000-PRINT-HEADER-EXIT
ELSE
MOVE SPACE to ASA-FILEREC
END-IF
perform 9050-PRINT-BLANK-LINE
thru 9050-PRINT-BLANK-LINE-EXIT
MOVE xml-entry-number to WS-COUNT
MOVE SPACES to FILEREC
STRING 'XMLCOB1I *** End of XML text reached. '
'Number of XML entries printed: ' WS-COUNT
delimited by size
INTO DATA-FILEREC
WRITE FILEREC
COMPUTE LPERPAGE-COUNT = LPERPAGE-COUNT + 1
57
Cobol, XML and XSD
.
9800-PRINT-XMLEND-MSG-EXIT.
EXIT.
9820-PRINT-STARTXML.
IF LPERPAGE-COUNT + 1 >= MAX-PER-PAGE
MOVE 1 to ASA-FILEREC
LPERPAGE-COUNT
PERFORM 9000-PRINT-HEADER THRU 9000-PRINT-HEADER-EXIT
ELSE
MOVE SPACE to ASA-FILEREC
END-IF
perform 9050-PRINT-BLANK-LINE
thru 9050-PRINT-BLANK-LINE-EXIT
MOVE SPACES to FILEREC
STRING 'XMLCOB1I *** Starting to parse the generated XML'
delimited by size
INTO DATA-FILEREC
WRITE FILEREC
COMPUTE LPERPAGE-COUNT = LPERPAGE-COUNT + 1
.
9820-PRINT-STARTXML-EXIT.
EXIT.
/
9840-PRINT-XMLEND-OK.
IF LPERPAGE-COUNT + 1 >= MAX-PER-PAGE
MOVE 1 to ASA-FILEREC
LPERPAGE-COUNT
PERFORM 9000-PRINT-HEADER THRU 9000-PRINT-HEADER-EXIT
ELSE
MOVE SPACE to ASA-FILEREC
END-IF
perform 9050-PRINT-BLANK-LINE
thru 9050-PRINT-BLANK-LINE-EXIT
MOVE SPACES to FILEREC
STRING 'XMLCOB1I *** XML document was successfully pars
delimited by size
INTO DATA-FILEREC
WRITE FILEREC
COMPUTE LPERPAGE-COUNT = LPERPAGE-COUNT + 1
.
9840-PRINT-XMLEND-OK-EXIT.
EXIT.
/
9860-PRINT-XMLERROR.
INITIALIZE WS-MSGINFO-BLOCK
MOVE XML-CODE to XMLCODE-BIN
MOVE XMLRTN-BIN to XMLRTN
MOVE XMLRSN-BIN to XMLRSN
58
Cobol, XML and XSD
*
COMPUTE WS-MSGINFO-INDEX = 1
SET WS-MSGINFO-I to WS-MSGINFO-INDEX
STRING 'XMLCOB1E *** XML document error, XML-CODE : '
XMLCODE
delimited by size
INTO WS-MSGINFO-DATA(WS-MSGINFO-I)
COMPUTE WS-MSGINFO-INDEX = WS-MSGINFO-INDEX + 1
SET WS-MSGINFO-I to WS-MSGINFO-INDEX
perform 8300-SET-XMLRTN-MSG
thru 8300-SET-XMLRTN-MSG-EXIT
STRING 'XMLCOB1E *** XML document error, XML-RTN
XMLRTN ' ' XMLRTN-MSG
delimited by size
INTO WS-MSGINFO-DATA(WS-MSGINFO-I)
COMPUTE WS-MSGINFO-INDEX = WS-MSGINFO-INDEX + 1
SET WS-MSGINFO-I to WS-MSGINFO-INDEX
STRING 'XMLCOB1E *** XML document error, XML-RSN
XMLRSN ' ' XMLRSN-MSG
delimited by size
INTO WS-MSGINFO-DATA(WS-MSGINFO-I)
: '
: '
COMPUTE WS-MSGINFO-INDEX = WS-MSGINFO-INDEX + 1
SET WS-MSGINFO-I to WS-MSGINFO-INDEX
STRING 'XMLCOB1E *** XML document error, XML-EVENT:'
XML-EVENT (1:30)
delimited by size
INTO WS-MSGINFO-DATA(WS-MSGINFO-I)
COMPUTE WS-MSGINFO-INDEX = WS-MSGINFO-INDEX + 1
SET WS-MSGINFO-I to WS-MSGINFO-INDEX
STRING 'XMLCOB1E *** XML document error, XML-TEXT :'
XML-TEXT (1:length of DATA-FILEREC - 43)
delimited by size
INTO WS-MSGINFO-DATA(WS-MSGINFO-I)
COMPUTE WS-MSGINFO-INDEX = WS-MSGINFO-INDEX + 1
SET WS-MSGINFO-I to WS-MSGINFO-INDEX
MOVE '***' TO
WS-MSGINFO-DATA(WS-MSGINFO-I)(XMLERR-OFFSET + 40:3)
PERFORM VARYING WS-MSGINFO-I from 1 by 1
Until WS-MSGINFO-I > WS-MSGINFO-INDEX
WRITE FILEREC FROM WS-MSGINFO-BLOCK-ENTRY (WS-MSGINFO-I)
COMPUTE LPERPAGE-COUNT = LPERPAGE-COUNT + 1
END-PERFORM
.
9860-PRINT-XMLERROR-EXIT.
EXIT.
/
*****************************************************************
*
Subroutines.
8000-DATE-TIME
*
59
Cobol, XML and XSD
*
8100-GET-SYSID
*
*
8200-GUESS-LENGTH
*
*
8220-GUESS-XSD-LENGTH
*
*
8300-SET-XMLRTN-MSG
*
*
8400-READ-SCHEMA
*
*****************************************************************
8000-DATE-TIME.
ACCEPT WS-TIME
FROM TIME
ACCEPT WS-DATE-YYMMDD
FROM DATE
ACCEPT WS-DAY-YYDDD
FROM DAY
ACCEPT WS-DAY-OF-WEEK FROM DAY-OF-WEEK
.
8000-DATE-TIME-EXIT.
EXIT.
8100-GET-SYSID.
SET Address of PSA to Null
SET Address of CVT to flccvt
SET Address of SMCA to cvtsmca
* The MOVE below is necessary to actually access the SMCASID field
* Before that the SMCASID field cannot be used directly.
MOVE SMCASID to WS-SYSID
.
8100-GET-SYSID-EXIT.
EXIT.
8200-GUESS-LENGTH.
MOVE 0 to WS-NONZERO-POS
PERFORM VARYING WS-POS from 1 by 1
UNTIL WS-POS > 32760
IF generated-xml-text (WS-POS:1) > X'00'
COMPUTE WS-NONZERO-POS = WS-NONZERO-POS + 1
END-IF
END-PERFORM
Perform 9050-PRINT-BLANK-LINE
thru 9050-PRINT-BLANK-LINE-EXIT
MOVE SPACES to DATA-FILEREC
If WS-NONZERO-POS = 0
STRING 'XMLCOB2I *** XML generated buffer is empty! '
delimited by size
into DATA-FILEREC
Else
MOVE WS-NONZERO-POS to WS-ZCOUNT
STRING 'XMLCOB2I *** XML generated buffer contains '
WS-ZCOUNT
' bytes.'
delimited by size
into DATA-FILEREC
End-if
60
Cobol, XML and XSD
WRITE FILEREC
COMPUTE LPERPAGE-COUNT = LPERPAGE-COUNT + 1
If WS-NONZERO-POS = 0
Perform 9800-PRINT-XMLEND-MSG
thru 9800-PRINT-XMLEND-MSG-EXIT
Close MYPRINT
Goback
End-if
.
8200-GUESS-LENGTH-EXIT.
EXIT.
/
8300-SET-XMLRTN-MSG.
MOVE spaces to XMLRTN-MSG
XMLRSN-MSG
MOVE 'See the reason code in the XML SS Guide, appendix B'
to XMLRSN-MSG
Evaluate true
when XMLRTN = 0
MOVE 'Successful parsing'
to XMLRTN-MSG
when XMLRTN = 4
MOVE 'Parsing with warnings' to XMLRTN-MSG
when XMLRTN = 8
MOVE 'Parsing has failed'
to XMLRTN-MSG
when XMLRTN = 12
MOVE 'Document is not well-formed' to XMLRTN-MSG
when XMLRTN = 16
MOVE 'Parsing failed w/fatal errorg' to XMLRTN-MSG
when XMLRTN = 20
MOVE 'Load of the service failed' to XMLRTN-MSG
when XMLRTN = 24
MOVE 'Document not valid w/schema' to XMLRTN-MSG
when other
CONTINUE
End-evaluate
.
8300-SET-XMLRTN-MSG-EXIT.
EXIT.
/
8400-READ-SCHEMA.
* **
Open processing
Open INPUT TSTXSD
Perform 9050-PRINT-BLANK-LINE
thru 9050-PRINT-BLANK-LINE-EXIT
Move
TstXSD-Status to WS-FSTATUS
61
Cobol, XML and XSD
Move 'TSTXSD'
to WS-FNAME
Perform 9100-PRINT-FS-STATUS
thru 9100-PRINT-FS-STATUS-EXIT
IF TstXSD-Status > 0
CLOSE TSTXML
CLOSE MYPRINT
GOBACK
END-IF
Perform 9050-PRINT-BLANK-LINE
thru 9050-PRINT-BLANK-LINE-EXIT
* **
* **
* **
Read the SCHEMA in the working storage. This is actually
the OSR version generated using XSDOSRG utility.
This is a compressed file with LRECL=80
Set TSTXSD-NO-EOF to true
Compute WS-POS = 1
Initialize Schema-Area
Perform until TSTXSD-EOF-HIT
READ TSTXSD
AT END
Set TSTXSD-EOF-HIT to true
NOT AT END
Move TSTXSD-REC(1:80)
to Schema-Area(WS-POS:80)
Compute WS-POS = WS-POS + 80
Compute TSTXSD-count = TSTXSD-count + 1
END-READ
End-Perform
* ** Print the successful message.
IF LPERPAGE-COUNT + 1 >= MAX-PER-PAGE
MOVE 1 to ASA-FILEREC
LPERPAGE-COUNT
PERFORM 9000-PRINT-HEADER THRU 9000-PRINT-HEADER-EXIT
ELSE
MOVE SPACE to ASA-FILEREC
END-IF
MOVE SPACES to FILEREC
STRING 'XMLCOB1I *** End of TSTXSD file reached. '
'Number of entries read: ' TSTXSD-COUNT
delimited by size
INTO DATA-FILEREC
WRITE FILEREC
COMPUTE LPERPAGE-COUNT = LPERPAGE-COUNT + 1
perform 9050-PRINT-BLANK-LINE
thru 9050-PRINT-BLANK-LINE-EXIT
.
62
Cobol, XML and XSD
8400-READ-SCHEMA-EXIT.
EXIT.
/
*****************************************************************
*
XML Parser event handler procedure
*
*
*
* While processing the XML document on each event the parser
*
* detects this procedure is given control with the information *
* about the event.
*
*
*
* Note the procedure may decide to abort the parsing by
*
* setting XML-CODE to 1. The parser may decide to abort the
*
* parsing and informs the procedure by setting XML-EVENT to
*
* EXCEPTION.
*
*
*
*****************************************************************
XMLEVENT-HANDLER SECTION.
move spaces to XML-ELEMENT
Evaluate XML-EVENT
* ** Order XML events most frequent first
when 'START-OF-ELEMENT'
compute string-length-pointer = 1
String 'ELEM-START: '
'<' XML-TEXT '>' delimited by space
into XML-Element
with pointer string-length-pointer
Perform 9300-PRINT-XMLPARSED
thru 9300-PRINT-XMLPARSED-EXIT
when 'CONTENT-CHARACTERS'
Move
'CONTENTS : ' to XML-Element
Move XML-TEXT to XML-Element(12:)
Compute xml-document-length = function length(XML-TEXT)
Compute string-length-pointer = xml-document-length
Perform 9300-PRINT-XMLPARSED
thru 9300-PRINT-XMLPARSED-EXIT
when 'END-OF-ELEMENT'
compute string-length-pointer = 1
String '<ELEM-END : '
'</' XML-TEXT '>' delimited by space
into XML-Element
with pointer string-length-pointer
Perform 9300-PRINT-XMLPARSED
Perform 9300-PRINT-XMLPARSED
thru 9300-PRINT-XMLPARSED-EXIT
when 'ATTRIBUTE-NAME'
compute string-length-pointer = 1
String '<ATTRIBUTE: '
'<' XML-TEXT '>' delimited by space
into XML-Element
with pointer string-length-pointer
Perform 9300-PRINT-XMLPARSED
thru 9300-PRINT-XMLPARSED-EXIT
when 'ATTRIBUTE-CHARACTERS'
compute string-length-pointer = 1
63
Cobol, XML and XSD
String
'<ATTRBCHRS: '
XML-TEXT delimited by size
into XML-Element
with pointer string-length-pointer
Perform 9300-PRINT-XMLPARSED
thru 9300-PRINT-XMLPARSED-EXIT
when 'ATTRIBUTE-CHARACTER'
compute string-length-pointer = 1
String '<ATTRBCHAR: '
XML-TEXT delimited by size
into XML-Element
with pointer string-length-pointer
Perform 9300-PRINT-XMLPARSED
thru 9300-PRINT-XMLPARSED-EXIT
when 'START-OF-CDATA-SECTION'
compute string-length-pointer = 1
String '<CDATA
: '
'<' XML-TEXT '>' delimited by space
into XML-Element
with pointer string-length-pointer
Perform 9300-PRINT-XMLPARSED
thru 9300-PRINT-XMLPARSED-EXIT
when 'END-OF-CDATA-SECTION'
compute string-length-pointer = 1
String '<CDATA-END: '
'<' XML-TEXT '>' delimited by space
into XML-Element
with pointer string-length-pointer
Perform 9300-PRINT-XMLPARSED
thru 9300-PRINT-XMLPARSED-EXIT
when 'CONTENT-CHARACTER'
compute string-length-pointer = 1
String '<CNTNCHAR : '
XML-TEXT delimited by space
into XML-Element
with pointer string-length-pointer
Perform 9300-PRINT-XMLPARSED
thru 9300-PRINT-XMLPARSED-EXIT
when 'PROCESSING-INSTRUCTION-TARGET'
compute string-length-pointer = 1
String '<INSTRTGT : '
'<' XML-TEXT '>' delimited by space
into XML-Element
with pointer string-length-pointer
Perform 9300-PRINT-XMLPARSED
thru 9300-PRINT-XMLPARSED-EXIT
when 'PROCESSING-INSTRUCTION-DATA'
compute string-length-pointer = 1
String '<INSTRDATA: '
'<' XML-TEXT '>' delimited by space
into XML-Element
with pointer string-length-pointer
Perform 9300-PRINT-XMLPARSED
thru 9300-PRINT-XMLPARSED-EXIT
64
Cobol, XML and XSD
when 'COMMENT'
compute string-length-pointer = 1
String '<COMMENT:
'
'<' XML-TEXT '>' delimited by space
into XML-Element
with pointer string-length-pointer
Perform 9300-PRINT-XMLPARSED
thru 9300-PRINT-XMLPARSED-EXIT
when 'EXCEPTION'
------------------------------------------------------------Note, the below ranges of exception do not stop the
parsing:
1-99
100,001-165,535
200,001-265,535
Decoding of a big XMLCODE:
1. take its hexa value 798818 = x'0C3062' where
2. the first 2 digits are the return code (x'0C' = 12)
3. the two last bytes are the reason code (x'3062')
XRSN_CHAR_INVALID
*
*
*
*
*
*
*
*
*
*
*
*
* The XMLSS reason-codes are listed in XML System Services Guide
* Appendix B.
* ------------------------------------------------------------compute string-length-pointer = 1
compute xml-document-length = function length (XML-TEXT)
compute xml-document-length = xml-document-length + 1
move xml-code to xmlcode-bin
move xml-document-length to xmlerr-offset
String 'XMLCOB1E *** Exception at offset '
xmlerr-offset
' text starts with: '
generated-xml-text(xmlerr-offset:)
delimited by size
into XML-Element
with pointer string-length-pointer
Perform 9300-PRINT-XMLPARSED
thru 9300-PRINT-XMLPARSED-EXIT
when other
compute string-length-pointer = 1
display 'Unexpected XML event: ' XML-EVENT '.'
String '<! Unexpected:' XML-EVENT '>'
XMl-EVENT (1:30)
delimited by size
into XML-Element
with pointer string-length-pointer
Perform 9300-PRINT-XMLPARSED
thru 9300-PRINT-XMLPARSED-EXIT
end-evaluate
.
65
Cobol, XML and XSD
1.2. The XSD processing
The validation of XML data against a Schema file (XSD) requires an OSR file that has been generated
from a XSD source. This section shows different ways to generate an OSR file.
Here's the XSD source.
<?xml version="1.0" encoding="IBM-1140"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- ========================================== -->
<!-- List
decription
-->
<!-- ========================================== -->
<xs:element name="test-list" type="list_type"/>
<!-- ========================================== -->
<!-- Main type describes an element of the list -->
<!-- ========================================== -->
<xs:complexType name="list_type">
<xs:sequence minOccurs="1" maxOccurs="99">
<xs:element name="test-entry" type="entry_type"/>
</xs:sequence>
</xs:complexType>
<!-- ================== -->
<!-- Subtypes
-->
<!-- ================== -->
<xs:complexType name="entry_type">
<xs:sequence>
<xs:element name="individual-ID"
type="xs:string"/>
<xs:element name="individual-name" type="name_type"/>
<xs:element name="individual-a2"
type="a2_type"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="name_type">
<xs:sequence>
<xs:element name="lastname" type="xs:string"/>
<xs:element name="firstname" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="a2_type">
<xs:sequence>
<xs:element name="country-code"
type="xs:string"/>
<xs:element name="redbooks-number" type="xs:int"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
This OSR file can be generated in the USS or in a batch job.
• Process a Schema file in the USS. This processing requires the XML toolkit (sys/XML/HXML19x) and
the xdsosrg tool available in the path. The xsdosrg tool may have been copied to the /bin folder in the
USS along a number of utilities.
• Copy this source as tstxsd.xsd in your xml folder
66
Cobol, XML and XSD
• In the xml folder type
xsdosrg -v -o tstxsd.osr tstxsd.xsd
• The resulting OSR file can be copied to a PDS using the command
cp txtxsd.osr "//'userid.xml.source(txtxsd)'"
• Process a Schema file in a batch job
• The xsdosrg module can be copied to a PDSE using the command
cp /bin/xsdosrg "//'userid.xml.pdseload(xsdosrg)'"
• Alernatively the xdsosrg module can be linked in a batch job and executed
//USERIDX JOB accnt,'Gen OSR module',CLASS=A
//COPYMOD EXEC PGM=IEWBLINK,PARM='LIST,MAP,CASE=MIXED,NOCALL'
//SYSLMOD DD
DISP=SHR,DSN=USERID.XML.PDSELOAD(XSDOSRG)
//SYSPRINT DD
SYSOUT=A
//SYSOBJ
DD
PATH='//bin/xsdosrg',PATHDISP=(KEEP,KEEP)
//SYSLIN
DD
*
INCLUDE SYSOBJ
ENTRY xsdosrg#C
NAME XSDOSRG(R)
/*
//*
//* Execute xsdosrg
//*
//XSDOSRG EXEC PGM=XSDOSRG,
// PARM='/ -v -o /xml/tstxsd.osr xml/tstxsd.xsd'
//STEPLIB DD
DISP=SHR,DSN=USERID.XML.PDSELOAD
//
DD
DISP=SHR,DSN=SYS1.CSSLIB
//ENV
DD
PATH='/a/userid/xml/xsd2osr.env',PATHOPTS=(ORDONLY),
//
PATHDISP=(KEEP,KEEP)
//CEEOPTS DD
*
ENVAR("_CEE_ENVFILE=DD:ENV"),
RPTOPTS(ON),RPTSTG(ON),POSIX(ON),
ANYHEAP(4M,128K,ANYWHERE,FREE),
HEAP(92M,256K,ANYWHERE,KEEP,8192,4096)
//STDERR
DD
SYSOUT=*
//STDOUT
DD
SYSOUT=*
• Whatever the execution mode the USS must be set up with a number of adequates variables. For this
purpose create a xsd2osr.env file right in the xml folder and copy these thrre lines.
_BPX_BATCH_UMASK=0022
_BPX_BATCH_SPAWN=YES
_BPX_SHAREAS=YES
67
Cobol, XML and XSD
The execution of the xdsosrg module in the USS produces messages such as
USERID:/a/userid/xml: >xsdosrg -v -o tstxsd.osr tstxsd.xsd
OSR file: tstxsd.osr
Number of schemas: 1
Schema file: tstxsd.xsd
--- Calling gxluInitOSRG ---¨
--- Calling gxluLoadSchema ---¨ #1
--- Calling gxluGenOSR ---¨
Writing the OSR to: tstxsd.osr
--- Calling gxluControlOSRG ---¨
--- Calling gxluTermOSRG ---¨
USERID:/a/userid/xml: >
68
Cobol, XML and XSD
1.3. The build of the module and its execution
Because all the Cobol options are passed in the cbl statement in the Cobol source there is no specific
requirement to compile and link it. A standard Cobol JCL should be enough. The copybook must be
available to the Cobol compiler through the SYSLIB allocation.
The execution of program XMLCOB1 requires the following
• The OSR must be allocated as TSTXSD. The OSR file may be member of a PDS or reside in the USS.
• The output goes to TSTXML, a data set with DCB=(LRECL=80,RECFM=FB,BLKSIZE=4160).
//useridX
//GO
//STEPLIB
//SYSPRINT
//TSTXML
//TSTXSD
//** TSTXSD
//SYSPRINT
//SYSIN
JOB
EXEC
DD
DD
DD
DD
DD
DD
DD
accnt,'Run module',CLASS)A
PGM=XMLCOB1
DISP=SHR,DSN=userid.PDSELOAD
SYSOUT=*
DISP=SHR,DSN=userid.xml.source(TSTXML)
DISP=SHR,DSN=userid.xml.source(TSTOSR3)
PATH='/a/userid/xml/tstosr3.xsd'
SYSOUT=*
DUMMY
XMLCOB1 produces a TSTXML output like
<?xml version="1.0" encoding="ibm_1140"?>
<test_list>
<test_entry>
<individual_id>
XYZ00001</individual_id>
<individual_name>
<lastname>
COTTE</lastname>
<firstname>
Patrice</firstname>
</individual_name>
<individual_a2>
<country_code>
DE</country_code>
<redbooks_number>
32767</redbooks_number>
</individual_a2>
</test_entry>
<test_entry>
<individual_id>
02A546Z9</individual_id>
<individual_name>
<lastname>
GARCIA</lastname>
<firstname>
Andy</firstname>
69
Cobol, XML and XSD
</individual_name>
<individual_a2>
<country_code>
DK</country_code>
<redbooks_number>
1</redbooks_number>
</individual_a2>
</test_entry>
</test_list>
XMLCOB1 produces a report as shown below
XMLCOB1 Utility v1r0
System XXXX
XMLCOB1I *** File SYSPRINT successfully opened
Field individual-name (0001) COTTE
Field individual-name (0002) GARCIA
Patrice
Andy
XMLCOB1I *** XML document was successfully parsed
XMLCOB2I *** XML generated buffer contains
XMLCOB1I *** File TSTXML
572 bytes.
successfully opened
<?xml version="1.0" encoding="IBM-1140"?><test-list><test-entry><individual-ID>XYZ0
TTE</lastname><firstname>Patrice</firstname></individual-name><individual-a2><count
redbooks-number></individual-a2></test-entry><test-entry><individual-ID>02A546Z9</i
astname><firstname>Andy</firstname></individual-name><individual-a2><country-code>D
er></individual-a2></test-entry></test-list>
XMLCOB1I *** End of XML text reached. Number of XML entries printed: 000000002
XMLCOB1I *** Starting to parse the generated XML
XMLCOB1I *** File TSTXSD
successfully opened
XMLCOB1I *** End of TSTXSD file reached. Number of entries read: 0266
<! Start of document >
</Version:1.0>
</Encoding:IBM-1140>
ELEM-START:<test-list>
ELEM-START:<test-entry>
ELEM-START:<individual-ID>
CONTENTS :XYZ00001
<ELEM-END</individual-ID>
ELEM-START:<individual-name>
70
Cobol, XML and XSD
ELEM-START:<lastname>
CONTENTS :COTTE
<ELEM-END</lastname>
ELEM-START:<firstname>
CONTENTS :Patrice
<ELEM-END</firstname>
<ELEM-END</individual-name>
ELEM-START:<individual-a2>
ELEM-START:<country-code>
CONTENTS :DE
<ELEM-END</country-code>
ELEM-START:<redbooks-number>
CONTENTS :32767
<ELEM-END</redbooks-number>
<ELEM-END</individual-a2>
<ELEM-END</test-entry>
ELEM-START:<test-entry>
ELEM-START:<individual-ID>
CONTENTS :02A546Z9
<ELEM-END</individual-ID>
ELEM-START:<individual-name>
ELEM-START:<lastname>
CONTENTS :GARCIA
<ELEM-END</lastname>
ELEM-START:<firstname>
CONTENTS :Andy
<ELEM-END</firstname>
<ELEM-END</individual-name>
ELEM-START:<individual-a2>
ELEM-START:<country-code>
CONTENTS :DK
<ELEM-END</country-code>
ELEM-START:<redbooks-number>
CONTENTS :1
<ELEM-END</redbooks-number>
<ELEM-END</individual-a2>
<ELEM-END</test-entry>
<ELEM-END</test-list>
<! End of document >
XMLCOB1I *** XML document was successfully parsed.
71
Cobol, XML and XSD
2. The XMLQRY1 example
This program is based on the example in Appendix B.4 of the 'IBM XML for Z/OS processing' manual.
The XML System Services can be invoked for other purposes than parsing an XML stream. This program
calls program GXL1QXD to query information about the XML stream and environment.
Reference
The XML Processing in Z/OS manual, Chapter 8
The XML Processing in Z/OS manual, Appendix B.4
Requirements
• User has access to the TSO/E environment and can execute the IBM Cobol compiler at level V4 or higher
72
Cobol, XML and XSD
2.1. The Cobol program
Program XMLQRY1 operates as follows
• The TSTXML input is printed one record per line.
• On each read the record is concatenated to the existing QXD input buffer.
• Program calls the XML System Services querying information from the XML document declaration.
• The QXD output information is printed one item per line.
CBL XMLPARSE(XMLSS)
IDENTIFICATION DIVISION.
PROGRAM-ID. XMLQRY1.
*AUTHOR.
PATRICE COTTE.
* ------------------------------------------------ OK -*
IBM XML FOR ZOS PROCESSING.
*
Appendix B.4, Cobol example.
*
* This program calls the zOS XML System services to query
* the XML document declaration.
*
* This program reads from file TSTXML as many times
* as required to fill the 4K input-buffer. TSTXML is
* defined as F/4160. It can be the output of program
* XMLCOB1
*
* The output buffer is also a 4K buffer.
*
* Return-code Reason-code
* 4
1301
End of input buffer
* 8
1302
Output buffer small
* 4
1303
Output buffer ended
* 4
1304
Input and Output buffers end
*
* -----------------------------------------------------*INSTALLATION.
*DATE-MODIFIED.
DATE-COMPILED. 05/12/14
.
ENVIRONMENT DIVISION.
CONFIGURATION SECTION.
SPECIAL-NAMES.
ALPHABET HOST IS EBCDIC
C01 IS NEW-PAGE.
OBJECT-COMPUTER.
IBM-370-Z145.
* SOURCE-COMPUTER. IBM DEBUGGING MODE.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT TSTXML ASSIGN TO TSTXML
ORGANIZATION IS SEQUENTIAL
FILE STATUS IS TSTXML-STATUS.
73
Cobol, XML and XSD
SELECT MYPRINT ASSIGN TO SYSPRINT
FILE STATUS IS MYPRINT-STATUS.
DATA DIVISION.
FILE SECTION.
FD TSTXML
BLOCK CONTAINS 0 TO 4160 CHARACTERS
RECORDING MODE F
DATA RECORD IS TSTXML-REC
CODE-SET IS HOST.
01 TSTXML-REC
PIC X(80).
FD
01
MYPRINT
RECORDING MODE IS V
BLOCK CONTAINS 0 TO 3990 CHARACTERS
RECORD VARYING IN SIZE
FROM 1 TO 133 CHARACTERS
DEPENDING ON REC-SIZE
LABEL RECORD IS STANDARD
DATA RECORD IS FILEREC
CODE-SET IS HOST.
FILEREC.
05 ASA-FILEREC PIC X.
05 DATA-FILEREC PIC X(132).
/
WORKING-STORAGE SECTION.
77 MyPRINT-STATUS
PIC 9(2) VALUE 0.
77 TSTXML-STATUS
PIC 9(2) VALUE 0.
88 OPEN-OK
VALUE 0.
77 TSTXML-RECSIZE
PIC 9(4) COMP VALUE 80.
77 WS-MSGINFO-INDEX
PIC 9(5) COMP.
01 WS-MSGINFO-BLOCK.
03 WS-MSGINFO-LL
PIC 9(9) COMP VALUE 0.
03 WS-MSGINFO-BLOCK-ENTRY OCCURS 10 TIMES
INDEXED BY WS-MSGINFO-I.
05 WS-MSGINFO-ASA
PIC X.
05 WS-MSGINFO-DATA PIC X(80).
77 PAGE-COUNT
PIC 9(9) COMP VALUE 0.
77 LPERPAGE-COUNT
PIC 9(5) COMP VALUE 0.
77 MAX-PER-PAGE
PIC 9(5) COMP VALUE 60 .
77 PAGE-OFFSET
PIC 9(5) COMP VALUE 110.
77 DATE-OFFSET
PIC 9(5) COMP VALUE 105.
77 DATALEN
PIC 9(5) COMP VALUE 100.
77 REC-SIZE
PIC 9(8) COMP VALUE 133.
77 XMLREC-SIZE
PIC 9(8) COMP VALUE 1020.
*
ZCOUNT:Print field, Pcount:Page count, LCount:Loop count
77 WS-ZCOUNT
PIC ZZZZZ9.
77 WS-PCOUNT
PIC 9(4) COMP VALUE 0.
77 WS-LCOUNT
PIC 9(4) COMP VALUE 0.
77 WS-COUNT
PIC 9(8)
VALUE 0.
77 WS-POS
PIC 9(4) COMP VALUE 0.
77 WS-NONZERO-POS
PIC 9(9) COMP VALUE 0.
77 WS-LEN
PIC 9(9) COMP VALUE 0.
77 SUBT1
PIC 9(4) COMP VALUE 0.
77 WS-PRINT
PIC X
VALUE SPACES.
74
Cobol, XML and XSD
77
77
77
01
/
*
**
*
01
01
01
*
*
*
WS-STATUS
WS-FNAME
WS-SYSID
Ws-Misc.
05 rc
05 length-pointer
05 XMLSS-PGM
05 End-Of-File
PIC
PIC
PIC
Pic
Pic
Pic
Pic
9(2) VALUE 0.
X(8).
X(4).
s9(9) binary value 0.
s9(9) binary value 1.
x(8) value "GXL1QXD".
x value space.
Date/Time areas.
WS-DATETIME-HEADER
WS-DATE-YYYYMMDD.
10 WS-DATE-CENTURY
10 WS-DATE-YYMMDD.
15 WS-DATE-YEAR
15 WS-DATE-MONTH
15 WS-DATE-DAY
WS-DAY-YYYYDDD.
10 WS-DAY-CENTURY
10 WS-DAY-YYDDD.
15 WS-DAY-YEAR
15 WS-DAY-DAY
PIC
X(40)
VALUE SPACES.
PIC
9(02)
VALUE ZERO.
PIC
PIC
PIC
9(02)
9(02)
9(02)
VALUE ZERO.
VALUE ZERO.
VALUE ZERO.
PIC
9(02)
VALUE ZERO.
PIC
PIC
9(02)
9(03)
VALUE ZERO.
VALUE ZERO.
PIC
9
VALUE 1.
1:Monday to 7:Sunday.
01
01
WS-DAY-OF-WEEK
WS-TIME.
10 WS-TIME-HH
10 WS-TIME-MM
10 WS-TIME-SS
10 WS-TIME-DD
PIC
PIC
PIC
PIC
9(02)
9(02)
9(02)
9(02)
VALUE
VALUE
VALUE
VALUE
ZERO.
ZERO.
ZERO.
ZERO.
/
*
* ** Constants
*
77 SCALE1
PIC X(49) VALUE
' *----+----1----+----2----+----3----+----4----+-'.
77 SCALE2
PIC X(54) VALUE
'---5----+----6----+----7----+----8----+----9----+----0'.
/
*
* ** QXD area and fields.
*
01 QXD-Input.
03 QXD-Input-Structure.
05 QXD-Input-Workarea
Pic x(32768).
05 QXD-Input-Workarea-Length Pic s9(9) binary.
* ** Safe estimate for our XML example.
05 QXD-Input-Buffer
Pic x(3000).
05 QXD-Input-Buffer-Length
Pic s9(9) binary.
05 QXD-Output-Pointer
Usage is pointer.
05 QXD-Return-Code
Pic s9(9) binary.
75
Cobol, XML and XSD
05
01
01
01
*
*
01
01
01
QXD-Reason-code
Pic s9(9) binary.
QXD-Return-codes.
05 QXD-Retcode
88 QXD-success
QXD-Output-Display.
05 QXD-Version
05 QXD-xml-Autodet-Value
05 QXD-xml-Autodet-ccsid
05 QXD-xml-version
05 QXD-xml-release
05 QXD-xml-spec-ccsid
05 QXD-xml-flag1
05 QXD-xml-flag2
05 QXD-xml-reserved
05 QXD-xml-decl-length
Pic s9(9) binary.
Value 0.
Pic
Pic
Pic
Pic
Pic
Pic
Pic
Pic
Pic
Pic
zzzz9.
zzzz9.
zzzz9.
zzzz9.
zzzz9.
zzzz9.
x.
x.
zzzz9.
zzzz9.
XML-Doc-Len
Pic 9(8) COMP VALUE 1020.
LINKAGE SECTION.
The following system areas start at address 0 and do
not require a USING in the PROC DIV statement.
PSA.
05 FILLER
PIC X(16).
05 FLCCVT
POINTER.
CVT.
05 FILLER
PIC X(196).
05 CVTSMCA
POINTER.
SMCA.
05 FILLER
PIC X(16).
05 SMCASID
PIC X(4).
/
01
*
QXD-Output-STRUCTURE.
COPY GXLYQXD.
05 QXD-Version
05 QXD-XML-Autodet-Value
05 QXD-XML-Autodet-CCSID
05 QXD-XML-Version
05 QXD-XML-Release
05 QXD-XML-Spec-CCSID
05 QXD-XML-Flag1
05 QXD-XML-Flag2
05 QXD-XML-Reserved
05 QXD-Decl-Length
pic
pic
pic
pic
pic
pic
pic
pic
pic
pic
9(9)
9(9)
9(9)
9(4)
9(4)
9(9)
x.
x.
9(4)
9(9)
comp-5.
comp-5.
comp-5.
comp-5.
comp-5.
comp-5.
comp-5.
comp-5.
PROCEDURE DIVISION.
0000-MAINLINE SECTION.
Move Low-values to QXD-Input-Workarea
Move 32768
to QXD-Input-Workarea-Length
Move 0
to QXD-Return-Code QXD-Reason-code
Initialize
QXD-Output-Display.
Open OUTPUT
MYPRINT
76
Cobol, XML and XSD
Perform 9000-PRINT-HEADER
thru 9000-PRINT-HEADER-EXIT
Move MYPRINT-STATUS to WS-STATUS
Move 'SYSPRINT' to WS-FNAME
Perform 9100-PRINT-FS-STATUS
thru 9100-PRINT-FS-STATUS-EXIT
IF MYPRINT-STATUS >
GOBACK
END-IF
0
Open INPUT TstXML
Move TSTXML-STATUS to WS-STATUS
Move 'TSTXML'
to WS-FNAME
Perform 9100-PRINT-FS-STATUS
thru 9100-PRINT-FS-STATUS-EXIT
IF TSTXML-STATUS
Close MYPRINT
GOBACK
END-IF
* **
>
0
Read the XML document entirely into our buffer.
Initialize QXD-Input-Buffer
Initialize QXD-Input-Buffer-Length
Perform Read-XML-Doc
thru Read-Exit
Move 1 to Length-pointer
Perform String-XML-data
thru String-exit
until End-Of-file = "Y"
Perform 9050-PRINT-BLANK-LINE
thru 9050-PRINT-BLANK-LINE-EXIT
Perform 9200-PRINT-QXD-INPUT
thru 9200-PRINT-QXD-INPUT-EXIT
Perform 9050-PRINT-BLANK-LINE
thru 9050-PRINT-BLANK-LINE-EXIT
Perform 9050-PRINT-BLANK-LINE
thru 9050-PRINT-BLANK-LINE-EXIT
* **
Call zOS System services.
Call XMLSS-PGM using QXD-Input-Workarea
QXD-Input-Workarea-Length
QXD-Input-Buffer
QXD-Input-Buffer-Length
QXD-Output-Pointer
77
Cobol, XML and XSD
QXD-Return-Code
QXD-Reason-code
returning rc
Set address of QXD-Output-structure
to QXD-Output-pointer
COMPUTE length-pointer = 1
MOVE SPACES to FILEREC
MOVE WS-COUNT to WS-ZCOUNT
STRING 'XMLQRY1I *** XML Parser results follow:'
DELIMITED BY SIZE
INTO DATA-FILEREC
WITH POINTER length-pointer
IF LPERPAGE-COUNT + 1 >= MAX-PER-PAGE
MOVE 1 to ASA-FILEREC
LPERPAGE-COUNT
END-IF
COMPUTE REC-SIZE = length-pointer
WRITE FILEREC
COMPUTE LPERPAGE-COUNT = LPERPAGE-COUNT + 1
* **
If the System Services failed, say so.
If rc > 0
Perform 9050-PRINT-BLANK-LINE
thru 9050-PRINT-BLANK-LINE-EXIT
Move QXD-Return-Code to WS-ZCOUNT
Compute length-pointer = 1
String "Return-code: " WS-ZCOUNT
delimited by space into DATA-FILEREC
with pointer length-pointer
if lperpage-count + 1 >= max-per-page
move 1 to asa-filerec
lperpage-count
end-if
Compute rec-size = length-pointer
Write FILEREC
Compute lperpage-count = lperpage-count + 1
Move QXD-Reason-code to WS-ZCOUNT
compute length-pointer = 1
String "Reason-code: " WS-ZCOUNT
delimited by space into DATA-FILEREC
with pointer length-pointer
if lperpage-count + 1 >= max-per-page
move 1 to asa-filerec
lperpage-count
end-if
Compute rec-size = length-pointer
Write FILEREC
Compute lperpage-count = lperpage-count + 1
Stop run
End-If
78
Cobol, XML and XSD
* **
We are good, start reporting!
Evaluate QXD-Return-code
When 0
Set address of QXD-Output-structure
to QXD-Output-pointer
Move corresponding QXD-Output-Structure
to QXD-Output-Display
Perform
thru
Perform
thru
9050-PRINT-BLANK-LINE
9050-PRINT-BLANK-LINE-EXIT
9050-PRINT-BLANK-LINE
9050-PRINT-BLANK-LINE-EXIT
Compute length-pointer = 1
String "QXD version
: "
QXD-Version of QXD-Output-Display
delimited by size into DATA-FILEREC
with pointer length-pointer
if lperpage-count + 1 >= max-per-page
move 1 to asa-filerec
lperpage-count
end-if
Compute Rec-size = length-pointer
Write FILEREC
Compute lperpage-count = lperpage-count + 1
Compute length-pointer = 1
String "XML Autodet Value : "
QXD-XML-Autodet-value of QXD-Output-Display
delimited by size into DATA-FILEREC
with pointer length-pointer
if lperpage-count + 1 >= max-per-page
move 1 to asa-filerec
lperpage-count
end-if
Compute Rec-size = length-pointer
Write FILEREC
Compute lperpage-count = lperpage-count + 1
Compute length-pointer = 1
String "XML Autodet CCSID : "
QXD-XML-Autodet-CCSID of QXD-Output-Display
delimited by size into DATA-FILEREC
with pointer length-pointer
if lperpage-count + 1 >= max-per-page
move 1 to asa-filerec
lperpage-count
end-if
Compute Rec-size = length-pointer
Write FILEREC
Compute lperpage-count = lperpage-count + 1
Compute length-pointer = 1
79
Cobol, XML and XSD
String "XML Version
: "
QXD-XML-Version of QXD-Output-Display
delimited by size into DATA-FILEREC
with pointer length-pointer
if lperpage-count + 1 >= max-per-page
move 1 to asa-filerec
lperpage-count
end-if
Compute Rec-size = length-pointer
Write FILEREC
Compute lperpage-count = lperpage-count + 1
Compute length-pointer = 1
String "XML Release
: "
QXD-XML-Release of QXD-Output-Display
delimited by size into DATA-FILEREC
with pointer length-pointer
if lperpage-count + 1 >= max-per-page
move 1 to asa-filerec
lperpage-count
end-if
Compute Rec-size = length-pointer
Write FILEREC
Compute lperpage-count = lperpage-count + 1
Compute length-pointer = 1
String "XML Spec CCSID
: "
QXD-XML-Spec-CCSID of QXD-Output-Display
delimited by size into DATA-FILEREC
with pointer length-pointer
if lperpage-count + 1 >= max-per-page
move 1 to asa-filerec
lperpage-count
end-if
Compute Rec-size = length-pointer
Write FILEREC
Compute lperpage-count = lperpage-count + 1
Compute length-pointer = 1
String "XML Flag 1
: "
QXD-XML-Flag1
of QXD-Output-Display
delimited by size into DATA-FILEREC
with pointer length-pointer
if lperpage-count + 1 >= max-per-page
move 1 to asa-filerec
lperpage-count
end-if
Compute Rec-size = length-pointer
Write FILEREC
Compute lperpage-count = lperpage-count + 1
Compute length-pointer = 1
String "XML Flag 2
: "
80
Cobol, XML and XSD
QXD-XML-Flag2
of QXD-Output-Display
delimited by size into DATA-FILEREC
with pointer length-pointer
if lperpage-count + 1 >= max-per-page
move 1 to asa-filerec
lperpage-count
end-if
Compute Rec-size = length-pointer
Write FILEREC
Compute lperpage-count = lperpage-count + 1
Compute length-pointer = 1
String "XML Reserved
: "
QXD-XML-Reserved
of QXD-Output-Display
delimited by size into DATA-FILEREC
with pointer length-pointer
if lperpage-count + 1 >= max-per-page
move 1 to asa-filerec
lperpage-count
end-if
Compute Rec-size = length-pointer
Write FILEREC
Compute lperpage-count = lperpage-count + 1
Compute length-pointer = 1
String "XML Decl Length
: "
QXD-XML-Decl-Length of QXD-Output-Display
delimited by size into DATA-FILEREC
with pointer length-pointer
if lperpage-count + 1 >= max-per-page
move 1 to asa-filerec
lperpage-count
end-if
Compute Rec-size = length-pointer
Write FILEREC
Compute lperpage-count = lperpage-count + 1
Perform 9050-PRINT-BLANK-LINE
thru 9050-PRINT-BLANK-LINE-EXIT
End-Evaluate
Perform
thru
Perform
thru
9050-PRINT-BLANK-LINE
9050-PRINT-BLANK-LINE-EXIT
9800-PRINT-ENDMSG
9800-PRINT-ENDMSG-EXIT
Close TstXML
Close MYPRINT
.
0000-MAINLINE-EXIT.
Goback.
81
Cobol, XML and XSD
Read-XML-Doc.
Read TSTXML
AT END
Move "Y" to End-Of-File
Move TSTXML-STATUS to WS-STATUS
Perform 9150-PRINT-INPUT-SIZE
thru 9150-PRINT-INPUT-SIZE-EXIT
End-Read
Compute Ws-Count = WS-Count + 1
.
Read-Exit.
Exit.
String-XML-Data.
Scan backwards a record until '>' is found and compute
the text size in XMLREC-size.
Initialize SUBT1
Inspect function reverse (TSTXML-Rec)
tallying SUBT1 for characters before initial '>'
Compute XMLREC-Size = TSTXML-Recsize - SUBT1
*
*
*
Add Length of TSTXML record to QXD-Input-Buffer-Length
Add XMLREC-size to QXD-Input-Buffer-Length
*
Append the current record to the QXD buffer.
String TSTXML-REC (1:XMLREC-size)
delimited by size
into QXD-Input-Buffer
with Pointer Length-pointer.
*
Continue reading till end of file.
Perform Read-XML-Doc
thru Read-Exit
.
String-Exit.
Exit.
/
*****************************************************************
*
Print routines 9000-PRINT-HEADER
*
*
9050-PRINT-BLANK-LINE
*
*
9100-PRINT-FS-STATUS
*
*
9150-PRINT-INPUT-SIZE
*
*
9800-PRINT-ENDMSG
*
*****************************************************************
9000-PRINT-HEADER.
PERFORM 8000-DATE-TIME THRU 8000-DATE-TIME-EXIT
PERFORM 8100-GET-SYSID THRU 8100-GET-SYSID-EXIT
MOVE SPACES
to FILEREC
COMPUTE PAGE-COUNT = PAGE-COUNT + 1
MOVE
PAGE-COUNT to WS-PCOUNT
82
Cobol, XML and XSD
MOVE
1
to ASA-FILEREC
LPERPAGE-COUNT
MOVE 'XMLQRY1 Utility v1r0' to DATA-FILEREC
MOVE 'Page'
to DATA-FILEREC (PAGE-OFFSET:4)
MOVE WS-PCOUNT
to DATA-FILEREC (PAGE-OFFSET + 6:6)
COMPUTE REC-SIZE = PAGE-OFFSET + 6 + 6
WRITE FILEREC
MOVE SPACES
to FILEREC
MOVE 'System ' to DATA-FILEREC
MOVE WS-SYSID to DATA-FILEREC (8:4)
MOVE '20'
to DATA-FILEREC (DATE-OFFSET:2)
MOVE WS-DATE-YEAR to DATA-FILEREC(DATE-OFFSET
MOVE '-'
to DATA-FILEREC(DATE-OFFSET
MOVE WS-DATE-MONTH to DATA-FILEREC(DATE-OFFSET
MOVE '-'
to DATA-FILEREC(DATE-OFFSET
MOVE WS-DATE-DAY
to DATA-FILEREC(DATE-OFFSET
MOVE SPACES
to DATA-FILEREC(DATE-OFFSET
MOVE WS-TIME-HH
to DATA-FILEREC(DATE-OFFSET
MOVE ':'
to DATA-FILEREC(DATE-OFFSET
MOVE WS-TIME-MM
to DATA-FILEREC(DATE-OFFSET
COMPUTE REC-SIZE = DATE-OFFSET + 15 + 2
WRITE FILEREC
COMPUTE LPERPAGE-COUNT = LPERPAGE-COUNT + 1
MOVE SPACES to FILEREC
COMPUTE REC-SIZE = 1
WRITE FILEREC
COMPUTE LPERPAGE-COUNT = LPERPAGE-COUNT + 1
.
9000-PRINT-HEADER-EXIT.
EXIT.
9050-PRINT-BLANK-LINE.
MOVE SPACES to FILEREC
COMPUTE REC-SIZE = 1
IF LPERPAGE-COUNT + 1 >= MAX-PER-PAGE
EXIT
ELSE
WRITE FILEREC
COMPUTE LPERPAGE-COUNT = LPERPAGE-COUNT + 1
END-IF
.
9050-PRINT-BLANK-LINE-EXIT.
EXIT.
9100-PRINT-FS-STATUS.
SET
WS-MSGINFO-I to 1
MOVE 1 to WS-MSGINFO-INDEX
length-pointer
IF WS-STATUS
not = 00
MOVE SPACES to WS-MSGINFO-DATA(WS-MSGINFO-I)
STRING 'XMLQRY1E *** ' WS-FNAME
' File error, file-status: '
83
+
+
+
+
+
+
+
+
+
2:2)
4:1)
5:2)
7:1)
8:2)
10:2)
12:2)
14:1)
15:2)
Cobol, XML and XSD
WS-STATUS delimited by size
INTO WS-MSGINFO-DATA(WS-MSGINFO-I)
with pointer length-pointer
COMPUTE WS-MSGINFO-LL = length-pointer
COMPUTE WS-MSGINFO-INDEX = WS-MSGINFO-INDEX + 1
SET WS-MSGINFO-I to WS-MSGINFO-INDEX
END-IF
*
*
*
*
MOVE SPACES to FILEREC
EVALUATE TRUE
Successfull completion
.................0----+----1----+----2----+----3----+----4
WHEN WS-STATUS = 00
MOVE SPACES to WS-MSGINFO-DATA(WS-MSGINFO-I)
STRING 'XMLQRY1I *** File ' WS-FNAME
' successfully opened.'
DELIMITED by SIZE
into WS-MSGINFO-DATA(WS-MSGINFO-I)
with pointer length-pointer
MOVE 1 to WS-MSGINFO-INDEX
Successfull completion but ...
WHEN WS-STATUS = 02
STRING 'XMLQRY1I *** Duplicate key condition '
'when reading or writing an indexed file.'
DELIMITED by SIZE
into WS-MSGINFO-DATA(WS-MSGINFO-I)
with pointer length-pointer
MOVE 1 to WS-MSGINFO-INDEX
WHEN WS-STATUS = 04
STRING 'XMLQRY1I *** The record length does not'
' conform to the fixed file format.
'
DELIMITED by SIZE
into WS-MSGINFO-DATA(WS-MSGINFO-I)
with pointer length-pointer
MOVE 1 to WS-MSGINFO-INDEX
WHEN WS-STATUS = 05
STRING 'XMLQRY1I *** Open successful in I-O or '
'EXTEND mode, file has been created.
'
DELIMITED by SIZE
into WS-MSGINFO-DATA(WS-MSGINFO-I)
with pointer length-pointer
MOVE 1 to WS-MSGINFO-INDEX
WHEN WS-STATUS = 07
STRING 'XMLQRY1I *** Open for removal or Close '
'no rewind on a non-reel unit.
'
DELIMITED by SIZE
into WS-MSGINFO-DATA(WS-MSGINFO-I)
with pointer length-pointer
MOVE 1 to WS-MSGINFO-INDEX
At end conditions
WHEN WS-STATUS = 10
STRING 'XMLQRY1I *** At end condition on a Read'
'statement.
'
DELIMITED by SIZE
84
Cobol, XML and XSD
*
*
*
*
*
*
*
*
*
*
into WS-MSGINFO-DATA(WS-MSGINFO-I)
with pointer length-pointer
MOVE 1 to WS-MSGINFO-INDEX
WHEN WS-STATUS = 34
STRING 'XMLQRY1I *** Permanent error condition '
'trying to write beyond the file '
'boundaries.'
DELIMITED by SIZE
into WS-MSGINFO-DATA(WS-MSGINFO-I)
with pointer length-pointer
MOVE 1 to WS-MSGINFO-INDEX
WHEN WS-STATUS = 35
STRING 'XMLQRY1I *** An Open failed on a missing '
'non optional file.'
DELIMITED by SIZE
into WS-MSGINFO-DATA(WS-MSGINFO-I)
with pointer length-pointer
MOVE 1 to WS-MSGINFO-INDEX
WHEN WS-STATUS = 37
STRING 'XMLQRY1I *** An Open failed because the '
'open mode is not compatible with the file.'
DELIMITED by SIZE
into WS-MSGINFO-DATA(WS-MSGINFO-I)
with pointer length-pointer
MOVE 1 to WS-MSGINFO-INDEX
WHEN WS-STATUS = 38
STRING 'XMLQRY1I *** An Open failed because the '
'file has been closed with lock.'
DELIMITED by SIZE
into WS-MSGINFO-DATA(WS-MSGINFO-I)
with pointer length-pointer
MOVE 1 to WS-MSGINFO-INDEX
WHEN WS-STATUS = 39
STRING 'XMLQRY1I *** File Definition is not cons'
'sistent with a Fixed file attributes.'
DELIMITED by SIZE
into WS-MSGINFO-DATA(WS-MSGINFO-I)
with pointer length-pointer
MOVE 1 to WS-MSGINFO-INDEX
Logic error conditions
WHEN WS-STATUS = 41
WHEN WS-STATUS = 42
WHEN WS-STATUS = 43
WHEN WS-STATUS = 44
WHEN WS-STATUS = 46
WHEN WS-STATUS = 47
WHEN WS-STATUS = 48
WHEN WS-STATUS = 49
Implementor defined condition
WHEN WS-STATUS = 90
STRING 'XMLQRY1I *** File Definition is not cons'
'sistent with the actual file organization '
'about the record type.'
DELIMITED by SIZE
85
Cobol, XML and XSD
*
*
*
*
*
*
*
*
*
into WS-MSGINFO-DATA(WS-MSGINFO-I)
with pointer length-pointer
MOVE 1 to WS-MSGINFO-INDEX
WHEN WS-STATUS = 91
WHEN WS-STATUS = 92
WHEN WS-STATUS = 93
WHEN WS-STATUS = 94
WHEN WS-STATUS = 95
WHEN WS-STATUS = 96
WHEN WS-STATUS = 97
WHEN WS-STATUS = 98
WHEN WS-STATUS = 99
WHEN OTHER
CONTINUE
END-EVALUATE
* ** save message size for later printing
COMPUTE WS-MSGINFO-LL = length-pointer
IF LPERPAGE-COUNT + WS-MSGINFO-INDEX > MAX-PER-PAGE
MOVE 1 to WS-MSGINFO-ASA(1)
PERFORM 9000-PRINT-HEADER THRU 9000-PRINT-HEADER-EXIT
ELSE
MOVE SPACE to WS-MSGINFO-ASA(1)
END-IF
MOVE WS-MSGINFO-LL to REC-SIZE
PERFORM VARYING WS-MSGINFO-I from 1 by 1
Until WS-MSGINFO-I > WS-MSGINFO-INDEX
WRITE FILEREC FROM WS-MSGINFO-BLOCK-ENTRY (WS-MSGINFO-I)
COMPUTE LPERPAGE-COUNT = LPERPAGE-COUNT + 1
END-PERFORM
MOVE SPACES to FILEREC
COMPUTE REC-SIZE = 1
WRITE FILEREC
COMPUTE LPERPAGE-COUNT = LPERPAGE-COUNT + 1
.
9100-PRINT-FS-STATUS-EXIT.
EXIT.
9150-PRINT-INPUT-SIZE.
COMPUTE length-pointer = 1
MOVE SPACES to FILEREC
MOVE WS-COUNT to WS-ZCOUNT
STRING 'XMLQRY1I *** File ' WS-FNAME ', Records read: '
WS-ZCOUNT DELIMITED BY SIZE
INTO DATA-FILEREC
WITH POINTER length-pointer
IF LPERPAGE-COUNT + 1 >= MAX-PER-PAGE
MOVE 1 to ASA-FILEREC
LPERPAGE-COUNT
END-IF
86
Cobol, XML and XSD
COMPUTE REC-SIZE= length-pointer
WRITE FILEREC
COMPUTE LPERPAGE-COUNT = LPERPAGE-COUNT + 1
MOVE SPACES to FILEREC
MOVE QXD-Input-Buffer-Length to WS-ZCOUNT
COMPUTE length-pointer = 1
STRING 'XMLQRY1I *** File ' WS-FNAME ', Bytes read:
WS-ZCOUNT DELIMITED BY SIZE
INTO DATA-FILEREC
WITH POINTER length-pointer
IF LPERPAGE-COUNT + 1 >= MAX-PER-PAGE
MOVE 1 to ASA-FILEREC
LPERPAGE-COUNT
END-IF
COMPUTE REC-SIZE= length-pointer
WRITE FILEREC
COMPUTE LPERPAGE-COUNT = LPERPAGE-COUNT + 1
.
9150-PRINT-INPUT-SIZE-EXIT.
EXIT.
/
* ** Print the QXD input buffer by chunks of 132 bytes.
9200-PRINT-QXD-INPUT.
'
Compute length-pointer = 1
STRING 'XMLQRY1I *** Input to the XML Parser follows:'
DELIMITED BY SIZE
INTO DATA-FILEREC
WITH POINTER length-pointer
IF LPERPAGE-COUNT + 1 >= MAX-PER-PAGE
MOVE 1 to ASA-FILEREC
LPERPAGE-COUNT
END-IF
COMPUTE REC-SIZE= length-pointer
WRITE FILEREC
COMPUTE LPERPAGE-COUNT = LPERPAGE-COUNT + 1
Perform 9050-PRINT-BLANK-LINE
thru 9050-PRINT-BLANK-LINE-EXIT
MOVE 1 to WS-POS
MOVE 133 to REC-SIZE
MOVE 0 to WS-COUNT
PERFORM
UNTIL WS-POS >= QXD-input-buffer-length
MOVE SPACES to FILEREC
* ** Honor the LPER value but don't print the header on each
* ** page.
87
Cobol, XML and XSD
IF LPERPAGE-COUNT + 1 >= MAX-PER-PAGE
MOVE 1 to ASA-FILEREC
LPERPAGE-COUNT
ELSE
MOVE SPACE to ASA-FILEREC
END-IF
* ** Move part of the QXD buffer to the print line. On the
* ** last segment the number of characters to print is
* ** len-pos +1.
COMPUTE WS-LEN = QXD-input-buffer-length - WS-POS
IF WS-LEN <= REC-SIZE - 1
COMPUTE REC-SIZE = WS-LEN + 2
END-IF
MOVE QXD-Input-Buffer(WS-POS:REC-SIZE - 1)
to DATA-FILEREC
WRITE FILEREC
COMPUTE LPERPAGE-COUNT = LPERPAGE-COUNT + 1
COMPUTE WS-POS = WS-POS + REC-SIZE - 1
END-PERFORM
.
9200-PRINT-QXD-INPUT-EXIT.
EXIT.
/
9800-PRINT-ENDMSG.
IF LPERPAGE-COUNT + 1 >= MAX-PER-PAGE
MOVE 1 to ASA-FILEREC
LPERPAGE-COUNT
PERFORM 9000-PRINT-HEADER THRU 9000-PRINT-HEADER-EXIT
ELSE
MOVE SPACE to ASA-FILEREC
END-IF
MOVE SPACES to DATA-FILEREC
WRITE FILEREC
COMPUTE LPERPAGE-COUNT = LPERPAGE-COUNT + 1
MOVE SPACES to FILEREC
MOVE 'XMLQRY1I *** End of XML text reached. '
TO DATA-FILEREC
WRITE FILEREC
COMPUTE LPERPAGE-COUNT = LPERPAGE-COUNT + 1
.
9800-PRINT-ENDMSG-EXIT.
EXIT.
*****************************************************************
*
Subroutines.
8000-DATE-TIME
*
88
Cobol, XML and XSD
*
8100-GET-SYSID
*
*****************************************************************
8000-DATE-TIME.
ACCEPT WS-TIME
FROM TIME
ACCEPT WS-DATE-YYMMDD
FROM DATE
ACCEPT WS-DAY-YYDDD
FROM DAY
ACCEPT WS-DAY-OF-WEEK FROM DAY-OF-WEEK
.
8000-DATE-TIME-EXIT.
EXIT.
8100-GET-SYSID.
SET Address of PSA to Null
SET Address of CVT to flccvt
SET Address of SMCA to cvtsmca
* The MOVE below is necessary to actually access the SMCASID field
* Before that the SMCASID field cannot be used directly.
MOVE SMCASID to WS-SYSID
.
8100-GET-SYSID-EXIT.
EXIT.
89
Cobol, XML and XSD
2.2. The build of the module and its execution
This program can be compiled using a standard compile and link job.
The input of this job can be the XML source that XMLCOB1 program created.
//useridX JOB accnt,'Run module',CLASS=A
//GO
EXEC PGM=XMLQRY1
//STEPLIB
DD
DISP=SHR,DSN=userid.XML.PDSELOAD
//SYSPRINT
DD
SYSOUT=*
//TSTXML
DD
DISP=SHR,DSN=userid.XML.SOURCE(TSTXML)
//SYSPRINT
DD
SYSOUT=*
//SYSIN
DD
DUMMY
XMLQRY1 produces a report as shown below.
XMLQRY1 Utility v1r0
System XXXX
XMLQRY1I *** File SYSPRINT successfully
opened.
XMLQRY1I *** File TSTXML
successfully
opened.
XMLQRY1I *** File TSTXML
XMLQRY1I *** File TSTXML
, Records read:
, Bytes read:
35
572
XMLQRY1I *** Input to the XML Parser follows:
<?xml version="1.0" encoding="ibm_1140"?><test_list><test_entry><individual_id>XYZ0
TTE</lastname><firstname>Patrice</firstname></individual_name><individual_a2><count
redbooks_number></individual_a2></test_entry><test_entry><individual_id>02A546Z9</i
astname><firstname>Andy</firstname></individual_name><individual_a2><country_code>D
er></individual_a2></test_entry></test_list>
XMLQRY1I *** XML Parser results follow:
QXD version
:
1
XML Autodet Value :
8
XML Autodet CCSID :
37
XML Version
:
1
XML Release
:
0
XML Spec CCSID
: 1140
XML Flag 1
: .
XML Flag 2
: XML Reserved
:
0
XML Decl Length
:
0
90
Chapter 3. C++ and XML
This chapter goes one step further and deals with the interface between C++ programs and XML parsers.
It is based on the examples that come with the XML toolkit for z/OS.
There are three sets of examples further down referred as
• The samples programs. These programs are examples of using the XML Parser, C++ Edition.
• The zsamples programs. These programs deal with using Z/OS specific classes of the XML Parse, C
++ Edition.
• The xslt programs call the Xalan transformer to produce new documents from xml documents.
Reference
The XML Toolkit for z/OS User's Guide
Requirements
• User has access to the TSO/E environment
• User has access to the USS
• The XML Toolkit is available. Its usual location is like /usr/lpp/ixm/IBM/xml4c-5_x
• The Transformer part of the XML toolkit is installed in /usr/lpp/ixm/IBM/xslt4c-1_11
In the next pages we assume the tookit is installed in /usr/lpp/ixm/IBM/xml4c-5_7. It will also be assumed
user has created a folder named /a/userid/xml
The toolkit contains
• The XML Parser, C++ Edition, which is based on the Xerces Apache Foundation open source
• The XSLT Processor, C++ Edition, which is based on the Xalan Apache Foundation open source
• In the xml4c folder, a 'samples' subfolder
• In the xml4c folder, a 'zsamples' subfolder
• In the xslt4c folder, a 'samples' subfolder
The toolkit supports three modes of execution.
• 31-bit support non-XPLINK
• 31-bit support XPLINK
• 64-bit support. There's no 64-bit support non-XPLINK
XPLINK stands for Extra Performance Linkage. It is a special way of linking modules for better performances.
91
C++ and XML
1. Try the pre-installed IBM samples programs
This section explains how to make sure the XML Toolkit is installed properly by running the pre-built
IBM samples programs. IBM provides pre-built versions of each set of the samples, zsamples and xslt
programs. We here only deal with running the first set of examples.
Add and export these variables in your .profile or type the export commands to set up these variables in
your current session.
• export XERCESCROOT=/usr/lpp/ixm/IBM/xml4c-5_7
• export LIBPATH=$XERCESCROOT/lib:$LIBPATH
• export PATH=$XERCESCROOT/bin:$PATH (31-bit modes)
• export PATH=$XERCESCROOT/bin64:$PATH (64-bit mode)
• export XERCESCOUT=/a/userid/xml
Warning! Make sure you typed XERCESCROOT and XERCESCOUT with a 'C' following XERCES in
both.
Change your current directory and execute the DOMPrint sample
• cd $XERCESCROOT/samples/data
• DOMPrint -v=always -wenc=IBM-1047-s390 -wfpp=on personal.xml
If the Toolkit is installed and the environment set as suggested DOMPrint will 'print' XML lines to the
screen such as
<person id="two.worker">
<name>
<family>Worker</family>
<given>Two</given>
</name>
<email>two@foo.com</email>
<link manager="Big.Boss"/>
</person>
<person id="three.worker">
<name>
<family>Worker</family>
<given>Three</given>
</name>
<email>three@foo.com</email>
<link manager="Big.Boss"/>
</person>
<person id="four.worker">
<name>
<family>Worker</family>
<given>Four</given>
</name>
92
C++ and XML
<email>four@foo.com</email>
<link manager="Big.Boss"/>
</person>
The XML toolkit ships with these examples: C_Sample, CreateDOMDocument, DOMCount, DOMPrint,
EnumVal, MemParse, PParse, PSVIWriter, Redirect, SAX2Count, SAX2Print, SAXCount, SAXPrint,
SCMPrint, StdInParse.
See the XML toolkit for Z/OS User's guide, chapter 5 for a description of each example.
93
C++ and XML
2. Generate and execute the samples in the
USS
In this section we generate all the examples in a private folder and create a script that helps in the execution
of these many examples.
The are five steps for building and executing these programs:
• Get and install the GNU gmake utility
• Prepare your environment
• Configure and execute gmake
• Script the build of the examples
• Script the execution of the examples
94
C++ and XML
2.1. Get and install the GNU gmake utility
If the gmake utility is not in the all-purpose /bin directory of the USS it may be necessary to install it.
• Download the gmake.pax.Z.bin from this [http://www.ibm.com/servers/eserver/zseries/zos/unix/
bpxa1ty1.html#gmake] IBM page
• Copy the bin file right in /a/userid
• In /a/userid enter
pax –rzf gmake.pax.Z.bin
This will create the gmake utility in the /a/userid/bin folder
• Export PATH=$XERCESCROOT/bin64:$PATH (64-bit mode)
95
C++ and XML
2.2. Prepare your environment
Write authority is needed so it is likely you won't be able to (re)build the examples in the IBM installation
directory. Use the cp command to copy the examples to your private area. In the below XERCESCROOT
and XERCESCOUT are variables that contain the source and target locations and that you set up in the
prior section.
• cp -r $XERCESCROOT/samples $XERCESCOUT
96
C++ and XML
2.3. Configure and execute gmake
Enter these exports, the unset and configure commands
• export CXX=c++
• export CXXFLAGS="-2" ("-g" for debugging)
• export OS390_BIT64=1 (64-bit run; don't set for 31-bit modes)
• export OS390_XPLINK=1 (31-bit XPLINK mode)
• export PATH=/a/userid/bin:/a/userid/xml/samples:$PATH
• unset _CXX_CXXSUFFIX
• configure
The configure utility has created a Makefile for each sample
Finally enter
• gmake
to let the utility search all the sub-folders in your /samples location and build all the executables.
97
C++ and XML
2.4. Script the build of the examples
Alternatively you may create the script samples.bat in /a/userid/xml/samples that sets the variables and
performs the commands listed in the prior section.
• Create samples.bat using the below model.
#
# This script sets variables and executes the command that configure
# and build the samples.
#
echo "* Setting variables"
unset _CXX_CXXSUFFIX
export CXX=c++
export CXXFLAGS="-2"
#
# OS390_XPLINK=1
if building the 31-bit XPLINK samples
# OS390_BIT64=1
the 64-bit samples
export OS390_BIT64=1
#
# Just in case set XERCESCROOT path - it contains the version.incl
# file for gmake; set the XERCES output location. Make the samples
# directory the current directory.
#
export XERCESCROOT=/usr/lpp/ixm/IBM/xml4c-5_7
export XERCESCOUT=/a/userid/xml
echo "* Changing current directory "
cd
$XERCESCOUT/samples
#
# Run the configure script (must be in the path)
#
echo "* Execute configure "
configure
#
# Export variables for gmake
#
export _CXX_CXXSUFFIX=cpp
export _CXX_CCMODE=1
#
# Run gmake
#
echo "* Execute gmake"
gmake
#
##
### End of script
• Run samples.bat
The script prepares the environment and builds all the executables.
98
C++ and XML
2.5. Script the execution of the examples
Create in the /samples folder the xsamples.bat script that facilitate the execution of the examples
• Create xsamples.bat using the below model.
#
#
#
#
#
#
#
#
passing arguments to a shell script
$*
$@
$0
$n
$#
if test
then
echo
echo
echo
echo
echo
echo
echo
echo
echo
echo
echo
echo
echo
echo
echo
echo
echo
echo
echo
echo
echo
echo
echo
echo
echo
echo
echo
echo
echo
echo
echo
echo
echo
echo
echo
echo
=
=
=
=
=
the
the
the
the
the
complete string passed to the script
sequence of strings the argument is made of
script name
nth string
number of strings passed to the script.
"$1" = ""
' '
'============================================ '
'
'
'
XML Toolkit for z/OS
'
'
'
'Usage:
'
'
xsamples.bat executes the application '
'whose name is passed as an argument.
'
'
'
'The program must be available in the path.
'
'
'
'Each application processes the same xml
'
'input:
'
'
'
$XERCESCROOT/samples/data/personal.xml
'============================================ '
' '
'The following applications are available:
'
' '
'C_Sample
$XERCESCROOT/samples/data/personal.xml '
' An example of a C program that calls the XML
'
' parser, C++ edition
'
'
'
'CreateDOMDocument
(no parameter)
'
' This program creates a new DOM document from scratch
'
in memory.
' It then prints the count of elements in the tree.
'
'DOMCount -p $XERCESCROOT/samples/data/personal.xml
' Counts the elements, attributes, spaces and
'
' characters in an XML file
'
'
'
' use option -p for print
'
' use option -v=always to trigger the validation
'
'
'
'DOMPrint $XERCESCROOT/samples/data/personal.xml
'
99
'
'
'
'
'
C++ and XML
echo ' Parses the xml input file, then calls DOMWrite
'
echo ' to print the elements.
'
echo '
'
echo 'EnumVal
$XERCESCROOT/samples/data/personal.xml
'
echo ' Enumerates the markup declarations in a DTD file (?)'
echo '
'
echo 'MemParse -v=always
'
echo ' This program uses the SAX Parser to parse a memory
'
echo ' buffer containing XML statements, and reports the number'
echo ' of elements and attributes found.
'
echo '
'
echo 'PParse
-v=always $XERCESCROOT/samples/data/personal.xml'
echo ' Progressive parsing
'
echo '
'
echo 'PSVIWriter
'
echo ' ??
'
echo '
'
echo 'Redirect $XERCESCROOT/samples/data/personal.xml
'
echo ' Redirect the input stream for external entities. '
echo '
'
echo ' !! Current directory must contain direct.dtd !! '
echo '
'
echo 'SAX2Count $XERCESCROOT/samples/data/personal.xml
'
echo ' Counts the elements, attributes, spaces and characters '
echo ' in an XML file
'
echo '
'
echo 'SAX2Print $XERCESCROOT/samples/data/personal.xml
'
echo ' Parses an XML file and prints it out.
'
echo '
'
echo 'SAXCount $XERCESCROOT/samples/data/personal.xml
'
echo ' Counts the elements, attributes, spaces and characters '
echo ' in an XML file
'
echo '
'
echo 'SAXPrint $XERCESCROOT/samples/data/personal.xml
'
echo ' Parses an XML file and prints it out.
'
echo '
'
echo 'SCMPrint $XERCESCROOT/samples/data/personal.xsd
'
echo ' This program parses XML Schema file(s), to show how one can
echo ' access the Schema Content Model information.
echo '
'
echo 'SEnumVal $XERCESCROOT/samples/data/personal-schema.xml'
echo ' Enumerates the markup declarations in a schema
'
echo ' file
'
echo '
'
echo 'StdInParse -v=always <$XERCESCROOT/samples/data/personal.xsd
echo ' streaming XML data from standard input
echo ' '
echo ' !! Current directory must contain personal.dtd !!'
echo '
'
elif test "$1" = "CreateDOMDocument"
then
if test "$2" != ""
then
echo '***'
100
'
'
'
'
C++ and XML
echo '*** CreateDOMDocument doee not accept any parameter'
echo '***'
fi
CreateDOMDocument
#
# Cannot continue the if test on several lines!
#
elif test "$1" = "C_Sample" -o "$1" = "DOMCount" -o "$1" = "DOMPrint"
then
echo '***'
echo '*** xsamples.bat is starting the execution of '$1
echo '***'
$1 $XERCESCROOT/samples/data/personal.xml
echo
echo
echo
elif test
then
echo
echo
echo
'***'
'*** Program has ended an returned control to xsamples.bat'
'***'
"$1" = "EnumVal" -o "$1" = "PParse"
-o "$1" = "SAXCount"
'***'
'*** xsamples.bat is starting the execution of '$1
'***'
$1 $XERCESCROOT/samples/data/personal.xml
echo
echo
echo
elif test
then
echo
echo
echo
'***'
'*** Program has ended an returned control to xsamples.bat'
'***'
"$1" = "SAXPrint" -o "$1" = "SAX2Count" -o "$1" = "SAX2Print"
'***'
'*** xsamples.bat is starting the execution of '$1
'***'
$1 $XERCESCROOT/samples/data/personal.xml
echo
echo
echo
elif test
then
echo
echo
echo
'***'
'*** Program has ended an returned control to xsamples.bat'
'***'
"$1" = "MemParse"
$1
'***'
'*** xsamples.bat is starting the execution of '$1
'***'
echo
echo
echo
elif test
then
echo
-v=always
'***'
'*** Program has ended an returned control to xsamples.bat'
'***'
"$1" = "Redirect"
'***'
101
C++ and XML
echo
echo
echo
echo
cd
$1
'*** xsamples.bat is starting the execution of '$1
'***'
'*** >>> Current directory now ' $XERCESCROOT/samples/data
'***'
echo
echo
echo
elif test
then
echo
echo
echo
$XERCESCROOT/samples/data
$XERCESCROOT/samples/data/personal.xml
'***'
'*** Program has ended an returned control to xsamples.bat'
'***'
"$1" = "SCMPrint"
$1
'***'
'*** xsamples.bat is starting the execution of '$1
'***'
echo
echo
echo
elif test
then
echo
echo
echo
$XERCESCROOT/samples/data/personal.xsd
'***'
'*** Program has ended an returned control to xsamples.bat'
'***'
"$1" = "SEnumVal"
$1
'***'
'*** xsamples.bat is starting the execution of '$1
'***'
echo
echo
echo
elif test
then
echo
echo
echo
echo
echo
$XERCESCROOT/samples/data/personal-schema.xml
cd
$1
'***'
'*** Program has ended an returned control to xsamples.bat'
'***'
"$1" = "StdInParse"
'***'
'*** xsamples.bat is starting the execution of '$1
'***'
'*** >>> Current directory now ' $XERCESCROOT/samples/data
'***'
$XERCESCROOT/samples/data
-v=always <$XERCESCROOT/samples/data/personal.xml
echo '***'
echo '*** Program has ended an returned control to xsamples.bat'
echo '***'
else
echo '*** '
echo '*** Program name not recognized:' $1
echo '*** '
fi
102
C++ and XML
• Run xsamples.bat
• With no parameter xsamples.bat displays a help that gives the syntax for each program
• To execute a given program run xsamples.bat passing the name of this program and parameters as
expected by the program, for example
xsamples.bat SAX2Print $XERCESCROOT/samples/data/personal.xml
103
C++ and XML
3. Generate in the USS to a Z/OS load library
and execute in Z/OS
The steps for building and executing the programs in Z/OS are at a high level the same steps we followed
in the USS.
• Install gmake
• Prepare your environment
• Prepare a script that configures your environment in the USS
• Prepare a script that executes the gmake utility
• Execute the scripts and the resulting loadmodules in a Z/OS job
104
C++ and XML
3.1. Install gmake
See section "Get and Install the GNU make utility"
105
C++ and XML
3.2. Prepare your environment
The same settings that were used in the USS apply. Additional settings are required to route the generated
modules to a Z/OS library.
• export LOADMOD=userid.SAMPLES.REL.LOAD
• export LOADEXP=hlq.SIXMEXP
LOADMOD can be given any name. It must be a PDSE (Library) with at least 500 tracks, RECFM=U,
BLKSIZE=32760, LRECL=0
LOADEXP is the name of the Z/OS library that contains the toolkit. There is actually a set of libraries
whose last qualifier is like SIXM***
106
C++ and XML
3.3. Prepare the Configure script
We create a script that we can later execute in a Z/OS batch job.
• Create the zos-configure script in /a/userid/xml/samples
cd /a/userid/xml/samples
echo
echo 'Set variables for XML processing - similar to the USS setup'
echo
export XERCESCROOT=/usr/lpp/ixm/IBM/xml4c-5_7
export XERCESCOUT=/a/userid/xml
export XSLTROOT=/usr/lpp/ixm/IBM/xslt4c-1_11
export OS390BATCH=1
export OS390_BIT64=1
unset _CXX_SUFFIX
export CXX=c++
export CXXFLAGS="-2"
echo
'** XMLROOT
=' $XMLROOT
echo
'** XERCESCROOT =' $XERCESCROOT
echo
'** XERCESCOUT =' $XERCESCOUT
echo
'** XSLTROOT
=' $XSLTROOT
echo
'** OS390BATCH =' $OS390BATCH
echo
'** CXX
=' $CXX
echo
'** CXXFLAGS
=' $CXXFLAGS
echo
'** OS390_BIT64 =' $OS390_BIT64
echo
echo 'Set additional variables for z/OS processing'
echo
export LOADMOD=userid.SAMPLES.REL.LOAD
export LOADEXP=hlq.SIXMEXP
echo
'** LOADMOD
=' $LOADMOD
echo
'** LOADEXP
=' $LOADEXP
echo
echo 'Running the configure script'
echo
configure
107
C++ and XML
3.4. Prepare a gmake script
This script will be executed in a Z/OS batch job.
• Create the zos-gmake script in /a/userid/xml/samples
cd /a/userid/xml/samples
echo
echo 'Set variables for XML processing - similar to the USS setup'
echo
export XERCESCROOT=/usr/lpp/ixm/IBM/xml4c-5_7
export XERCESCOUT=/a/userid/xml
export XSLTROOT=/usr/lpp/ixm/IBM/xslt4c-1_11
export OS390_BIT64=1
unset _CXX_SUFFIX
export CXX=c++
export CXXFLAGS="-2"
export CXX_SUFFIX=cpp
export _CXX_CCMODE=1
echo
'** XMLROOT
=' $XMLROOT
echo
'** XERCESCROOT =' $XERCESCROOT
echo
'** XERCESCOUT =' $XERCESCOUT
echo
'** CXX
=' $CXX
echo
'** CXXFLAGS
=' $CXXFLAGS
echo
'** CXX_SUFFIX =' $CXX_SUFFIX
echo
'** _CXX_CCMODE =' $_CXX_CCMODE
echo
'** OS390_BIT64 =' $OS390_BIT64
echo
echo 'Set additional variables for z/OS processing'
echo
export LOADMOD=userid.SAMPLES.REL.LOAD
export LOADEXP=hlq.SIXMEXP
export _CXX_XSUFFIX_HOST=SIXMEXP
export OS390BATCH=1
echo
'** LOADMOD
=' $LOADMOD
echo
'** LOADEXP
=' $LOADEXP
echo
'** _CXX_XSUFFIX_HOST = ' $_CXX_XSUFFIX_HOST
echo
echo 'Running gmake
'
echo
gmake
108
C++ and XML
3.5. Execute the scripts and loadmodules in a Z/OS
batch job
Copy this JCL to your JCL library and customize to your needs.
This JCL contains conditional statements that can be set so that one or several steps are selected for execution. Each step executes depending on the value of its associated RUNnn variable. For example the
execution of the RUN06 step depends on the RUN06 variable contents. See the comments in the JCL
about setting the variables.
Additionally, should a particular step terminate with a return code bigger than 4, all the steps that follow
are automatically flushed.
In its entirety this job
• Creates a PDSE load library
• Executes the script zos-configure in the USS
• Executes the script zos-gmake in the USS
• Executes each of the generated modules, eacn in its own step.
//useridU JOB accnt,'BPXBATCH',CLASS=A
//*
//* ----------------------------------------------------------------//* This job requests UNIX SERVICES to setup the examples that
//* ship with XML toolkit for z/OS.
//*
//* About the running a USS oriented job
//*
UNIX SYSTEMS SERVICES USER'S GUIDE (BPXA409) , CHAPTER 11
//*
//* Strangely enough BPXBATCH does not support a STDIN Z/OS file
//* and the STDPARM can be used to pass one line command in place of
//* the exec parm.
//*
//* The DOCONF and DOGEN steps thus read pre-existing STDINs in
//* the USS.
//*
//* HFS is case sensitive - use Caps on
//* ----------------------------------------------------------------//* Building and executing the XML toolkit examples in z/OS
//* 1. It is assumed the XML Toolkit exists in the USS and the
//*
examples have been copied to a private location.
//* 2. The gmake utility exists or has been installed as explained
//*
in the manual XML ToolKit for z/OS User Guide, chapter 5,
//*
How to use the XML Parser C++ Edition
//*
//* This job
//*
//* 1. (Re-)allocate a PDSE load library, 500 tracks at least
//* 2. Configure the private location prior to the generation
//* 3. Generate the executables
109
C++ and XML
//* 4. Execute each example
//* ----------------------------------------------------------------//* The below SET statements drive the job execution or re-execution
//*
at step level
//* The 'RC < 5' string ensures this step will execute only if any
//*
prior step executed with a RC not bigger than 4
//* The 'RC > 20'string ensures this step will NOT execute after
//*
prior steps all returned a RC in the range 0-20,
//*
so basically this step should always be skipped.
//* ----------------------------------------------------------------//*
//
SET CREPDSE='RC < 5'
//
SET DOCONF='RC < 5'
//
SET DOGEN='RC < 5'
//
SET RUN01='RC > 20'
CRDOMDOC
//
SET RUN02='RC > 20'
CSAX2CNT
//
SET RUN03='RC < 5'
DOMCOUNT
//
SET RUN04='RC < 5'
DOMPRINT
//
SET RUN05='RC > 20'
ENUMVAL
//
SET RUN06='RC < 5'
MEMPARSE
//
SET RUN07='RC > 20'
PPARSE
//
SET RUN08='RC > 20'
PSVIWRIT
//
SET RUN09='RC > 20'
REDIRECT
//
SET RUN10='RC < 5'
SAXCOUNT
//
SET RUN11='RC < 5'
SAXPRINT
//
SET RUN12='RC < 5'
SAX2CONT
//
SET RUN13='RC < 5'
SAX2PRNT
//
SET RUN14='RC > 20'
SCMPRINT
//
SET RUN15='RC > 20'
SENUMVAL
//
SET RUN16='RC > 20'
STDINPAR
//
SET STEPLIB=userid.SAMPLES.REL.LOAD
//
SET IXMLOAD=hlq.SIXMLOD1
//*
//* ----------------------------------------------------------------//*
- Set MAXCC as appropriate to select the CREPDSE step on RC
//* ----------------------------------------------------------------//SETRC
EXEC PGM=IDCAMS
//SYSPRINT DD SYSOUT=*
//SYSIN
DD *
SET MAXCC=0
/*
//* ----------------------------------------------------------------//*
- Create PSDE load library
//* ----------------------------------------------------------------//
IF (&CREPDSE) THEN
//CREPDSE EXEC PGM=IDCAMS
//SYSPRINT DD
SYSOUT=*
//SYSIN
DD
*
DELETE
userid.SAMPLES.REL.LOAD
SET MAXCC=00
/* */
ALLOC DA('userid.SAMPLES.REL.LOAD') +
STORCLAS(TSO) DIR(0) DSORG(PO) +
LRECL(0) RECFM(U) BLKSIZE(32760) +
110
C++ and XML
DSNTYPE(LIBRARY)
SPACE (500,50) TRACKS
CATALOG
+
+
/*
//
ENDIF
//* ----------------------------------------------------------------//*
- Run the configure script
//* ----------------------------------------------------------------//
IF (&DOCONF) THEN
//RUNCONF EXEC PGM=BPXBATCH
//STDENV
DD *
LOGNAME=userid
HOME=/a/userid
_BPX_BATCH_SPAWN=YES
_BPX_SHAREAS=NO
_BPX_SPAWN_SCRIPT=YES
/*
//STDPARM DD DUMMY
//STDIN
DD PATH='/a/userid/xml/samples/zos-configure',
//
PATHOPTS=(ORDONLY)
//*TDOUT
DD PATH='/a/userid/xml/samples/zos-runconf.out',
//*
PATHOPTS=(OWRONLY,OCREAT),PATHMODE=SIRWXU
//*TDERR
DD PATH='/a/userid/xml/samples/zos-runconf.err',
//*
PATHOPTS=(OWRONLY,OCREAT),PATHMODE=SIRWXU
//*
//* Alternative outputs
//STDOUT
DD SYSOUT=*
//STDERR
DD SYSOUT=*
//SYSPRINT DD SYSOUT=*
//
ENDIF
//* ----------------------------------------------------------------//*
- Generate the the executables (gmake)
//* ----------------------------------------------------------------//
IF (&DOGEN) THEN
//GMAKE
EXEC PGM=BPXBATCH
//STDENV
DD *
LOGNAME=userid
HOME=/a/userid
_BPX_BATCH_SPAWN=YES
_BPX_SHAREAS=NO
_BPX_SPAWN_SCRIPT=YES
//STDPARM DD DUMMY
//STDIN
DD PATH='/a/userid/xml/samples/zos-gmake',
//
PATHOPTS=(ORDONLY)
//STDOUT
DD SYSOUT=*
//STDERR
DD SYSOUT=*
//*TDOUT
DD PATH='/a/userid/xml/samples/zos-gmake.out',
//*
PATHOPTS=(OWRONLY,OCREAT),PATHMODE=SIRWXU
//*TDERR
DD PATH='/a/userid/xml/samples/zos-gmake.err',
//*
PATHOPTS=(OWRONLY,OCREAT),PATHMODE=SIRWXU
//SYSPRINT DD SYSOUT=*
//*
/*
//
ENDIF
111
C++ and XML
//* ----------------------------------------------------------------//*
- Run the example #1
//* ----------------------------------------------------------------//
IF (&RUN01) THEN
//RUN01
EXEC PGM=CRDOMDOC,
// PARM=('///usr/lpp/ixm/IBM/xml4c-5_7/samples/data/personal.xml')
//*
//* Alternative syntaxes can be used to allocate a z/os file input
//*
//* PARM='///DD:XMLDATA(PERSONAL)'
//* PARM='DD:XMLDATA(PERSONAL)'
//*
//* PARM='"//''userid.XML.DATA(PERSONAL)''"'
//* PARM='"//XML.DATA(PERSONAL)"'
(automatic prefixation)
//*
//STEPLIB DD
DISP=SHR,DSN=&STEPLIB
//
DD
DISP=SHR,DSN=&IXMLOAD
//*XMLDATA DD
DISP=SHR,DSN=userid.XML.DATA
//
ENDIF
//* ----------------------------------------------------------------//*
- Run the example #2
//* ----------------------------------------------------------------//
IF (&RUN02) THEN
//RUN02
EXEC PGM=CSAX2CNT,
// PARM=('///usr/lpp/ixm/IBM/xml4c-5_7/samples/data/personal.xml')
//STEPLIB DD
DISP=SHR,DSN=&STEPLIB
//
DD
DISP=SHR,DSN=&IXMLOAD
//
ENDIF
//* ----------------------------------------------------------------//*
- Run the example #3
//* ----------------------------------------------------------------//
IF (&RUN03) THEN
//RUN03
EXEC PGM=DOMCOUNT,
// PARM=('///usr/lpp/ixm/IBM/xml4c-5_7/samples/data/personal.xml')
//STEPLIB DD
DISP=SHR,DSN=&STEPLIB
//
DD
DISP=SHR,DSN=&IXMLOAD
//
ENDIF
//* ----------------------------------------------------------------//*
- Run the example #4
//* ----------------------------------------------------------------//
IF (&RUN04) THEN
//RUN04
EXEC PGM=DOMPRINT,
// PARM=('///usr/lpp/ixm/IBM/xml4c-5_7/samples/data/personal.xml')
//STEPLIB DD
DISP=SHR,DSN=&STEPLIB
//
DD
DISP=SHR,DSN=&IXMLOAD
//
ENDIF
//* ----------------------------------------------------------------//*
- Run the example #5
//* ----------------------------------------------------------------//
IF (&RUN05) THEN
//RUN05
EXEC PGM=ENUMVAL,
// PARM=('///usr/lpp/ixm/IBM/xml4c-5_7/samples/data/personal.xml')
//STEPLIB DD
DISP=SHR,DSN=&STEPLIB
//
DD
DISP=SHR,DSN=&IXMLOAD
112
C++ and XML
//
ENDIF
//* ----------------------------------------------------------------//*
- Run the example #6
//* ----------------------------------------------------------------//
IF (&RUN06) THEN
//RUN06
EXEC PGM=MEMPARSE,
// PARM=('-v=always')
//STEPLIB DD
DISP=SHR,DSN=&STEPLIB
//
DD
DISP=SHR,DSN=&IXMLOAD
//
ENDIF
//* ----------------------------------------------------------------//*
- Run the example #7
//* ----------------------------------------------------------------//
IF (&RUN07) THEN
//RUN07
EXEC PGM=PPARSE,
// PARM=('///usr/lpp/ixm/IBM/xml4c-5_7/samples/data/personal.xml')
//STEPLIB DD
DISP=SHR,DSN=&STEPLIB
//
DD
DISP=SHR,DSN=&IXMLOAD
//
ENDIF
//* ----------------------------------------------------------------//*
- Run the example #8
//* ----------------------------------------------------------------//
IF (&RUN08) THEN
//RUN08
EXEC PGM=PSVIWRIT,
// PARM=('////usr/lpp/ixm/IBM/xml4c-5_7/samples/data/personal.xml')
//STEPLIB DD
DISP=SHR,DSN=&STEPLIB
//
DD
DISP=SHR,DSN=&IXMLOAD
//
ENDIF
//* ----------------------------------------------------------------//*
- Run the example #9
//* ----------------------------------------------------------------//
IF (&RUN09) THEN
//RUN09
EXEC PGM=REDIRECT,
// PARM=('///usr/lpp/ixm/IBM/xml4c-5_7/samples/data/personal.xml')
//STEPLIB DD
DISP=SHR,DSN=&STEPLIB
//
DD
DISP=SHR,DSN=&IXMLOAD
//
ENDIF
//* ----------------------------------------------------------------//*
- Run the example #10
//* ----------------------------------------------------------------//
IF (&RUN10) THEN
//RUN10
EXEC PGM=SAXCOUNT,
// PARM=('///usr/lpp/ixm/IBM/xml4c-5_7/samples/data/personal.xml')
//STEPLIB DD
DISP=SHR,DSN=&STEPLIB
//
DD
DISP=SHR,DSN=&IXMLOAD
//
ENDIF
//* ----------------------------------------------------------------//*
- Run the example #11
//* ----------------------------------------------------------------//
IF (&RUN11) THEN
//RUN11
EXEC PGM=SAXPRINT,
// PARM=('///usr/lpp/ixm/IBM/xml4c-5_7/samples/data/personal.xml')
//STEPLIB DD
DISP=SHR,DSN=&STEPLIB
//
DD
DISP=SHR,DSN=&IXMLOAD
113
C++ and XML
//
ENDIF
//* ----------------------------------------------------------------//*
- Run the example #12
//* ----------------------------------------------------------------//
IF (&RUN12) THEN
//RUN12
EXEC PGM=SAX2CONT,
// PARM=('///usr/lpp/ixm/IBM/xml4c-5_7/samples/data/personal.xml')
//STEPLIB DD
DISP=SHR,DSN=&STEPLIB
//
DD
DISP=SHR,DSN=&IXMLOAD
//
ENDIF
//* ----------------------------------------------------------------//*
- Run the example #13
//* ----------------------------------------------------------------//
IF (&RUN13) THEN
//RUN13
EXEC PGM=SAX2PRNT,
// PARM=('///usr/lpp/ixm/IBM/xml4c-5_7/samples/data/personal.xml')
//STEPLIB DD
DISP=SHR,DSN=&STEPLIB
//
DD
DISP=SHR,DSN=&IXMLOAD
//
ENDIF
//* ----------------------------------------------------------------//*
- Run the example #14
//* ----------------------------------------------------------------//
IF (&RUN14) THEN
//RUN14
EXEC PGM=SCMPRINT,
// PARM=('///usr/lpp/ixm/IBM/xml4c-5_7/samples/data/personal.xml')
//STEPLIB DD
DISP=SHR,DSN=&STEPLIB
//
DD
DISP=SHR,DSN=&IXMLOAD
//
ENDIF
//* ----------------------------------------------------------------//*
- Run the example #15
//* ----------------------------------------------------------------//
IF (&RUN15) THEN
//RUN15
EXEC PGM=SENUMVAL,
// PARM=('///usr/lpp/ixm/IBM/xml4c-5_7/samples/data/personal.xml')
//STEPLIB DD
DISP=SHR,DSN=&STEPLIB
//
DD
DISP=SHR,DSN=&IXMLOAD
//
ENDIF
//* ----------------------------------------------------------------//*
- Run the example #16
//* ----------------------------------------------------------------//
IF (&RUN16) THEN
//RUN16
EXEC PGM=STDINPAR,
// PARM=('///usr/lpp/ixm/IBM/xml4c-5_7/samples/data/personal.xml')
//STEPLIB DD
DISP=SHR,DSN=&STEPLIB
//
DD
DISP=SHR,DSN=&IXMLOAD
//
ENDIF
114
C++ and XML
4. Fully generate an example in Z/OS
In the prior section the build of the Z/OS load modules was performed in the USS. In this section we see
how an application can be entirely generated in a Z/OS batch job. Consider the SAX2Count example that
can be found in the USS. It is made of the following:
• The SAX2Count.cpp source
• The SAX2Count.hpp include
• The SAX2CountHandlers.cpp source
• The SAX2CountHandlers.hpp include
These sources will be copied to a Z/OS library and processed in Z/OS to generate and execute the
SAX2COUNT application in Z/OS.
Allocate PDSE data sets as detailed below
• userid.BATCH.CPP
recfm=FB, lrecl=240, blksize=12960
• userid.BATCH.HPP
recfm=FB, lrecl=240, blksize=12960
• userid.BATCH.JCL
recfm=FB, lrecl=80, blksize=12960
• userid.BATCH.OBJ
recfm=FB, lrecl=80, blksize=12960
• userid.BATCH.LOAD
recfm=U, lrecl=0, blksize=32760
• userid.BATCH.XML
recfm=FB, lrecl=80, blksize=12960
Copy and edit as follows
• Copy SAX2Count.cpp and SAX2CountHandlers.cpp as SAX2CNT and SAX2HND members to the
CPP library
cp SAX2Count.cpp "//'userid.BATCH.CPP(SAX2CNT)'"
cp SAX2CountHandlers.cpp "//'userid.BATCH.CPP(SAX2HND)'"
• Copy SAX2Count.hpp and SAX2CountHandlers.hpp as SAX2CNTH and SAX2HNDH members to
the HPP library
cp SAX2Count.hpp "//'userid.BATCH.HPP(SAX2CNTH)'"
cp SAX2CountHandlers.hpp "//'userid.BATCH.HPP(SAX2HNDH)'"
115
C++ and XML
• Edit SAX2CNT member and change in the #include "SAXCountHandlers.hpp" to "SAXConth.hpp"
// -----------------------------------------------------// Includes
// -----------------------------------------------------#include "SAX2CNTH.hpp"
#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/sax2/SAX2XMLReader.hpp>
#include <xercesc/sax2/XMLReaderFactory.hpp>
#if defined(XERCES_NEW_IOSTREAMS)
#include <fstream>
#else
#include <fstream.h>
#endif
#include <xercesc/util/OutOfMemoryException.hpp>
• Edit SAX2HND member and modify the #include as shown
// -------------------------------------------// Includes
// -------------------------------------------#include "SAX2CNTH.hpp"
#include <xercesc/sax2/Attributes.hpp>
#include <xercesc/sax/SAXParseException.hpp>
#include <xercesc/sax/SAXException.hpp>
• Last, edit SAX2HNDH member and modify the #include as shown
// --------------------------------------------------// Includes for all the program files to see
// --------------------------------------------------#include <xercesc/util/PlatformUtils.hpp>
#include <stdlib.h>
#include <string.h>
#if defined(XERCES_NEW_IOSTREAMS)
#include <iostream>
#else
#include <iostream.h>
#endif
#include "SAX2HNDH.hpp"
#include <xercesc/sax2/XMLReaderFactory.hpp>
#include <xercesc/sax2/SAX2XMLReader.hpp>
Create member XMLCPPJ in the JCL library and submit
116
C++ and XML
//useridX JOB accnt,'Gen and run',CLASS=A
//*
//
SET
MODULE=SAX2CNT
//
SET
IXMLOAD=hqual.SIXMLOD1
//*
//JOBLIB
DD DISP=SHR,DSN=CEE.SCEERUN
//
DD DISP=SHR,DSN=CEE.SCEERUN2
//
DD DISP=SHR,DSN=CBC.SCCNCMP
//*
//* --------------------------------------------------------------//* CPPPROC procedure invokes the CPP compiler
//* --------------------------------------------------------------//CPPPROC PROC MEMBER=,
//
SRCLIB=
//COMPILE EXEC PGM=CCNDRVR,PARM='/CXX OPTFILE(DD:OPTS),OBJ,LIST'
//SYSLIN
DD DISP=SHR,DSN=&SYSUID..BATCH.OBJ(&MEMBER)
//SYSPRINT DD SYSOUT=A
//SYSIN
DD DISP=SHR,DSN=&SRCLIB(&MEMBER)
//SYSUT1
DD DUMMY
//OPTS
DD DUMMY
//
PEND
//* --------------------------------------------------------------//* CPPLINK procedure invokes the linker in a CPP context
//* --------------------------------------------------------------//CPPLINK
PROC
//LINK
EXEC PGM=IEWL,PARM='OPTIONS=OPTS'
//SYSLIB
DD
DISP=SHR,DSN=CEE.SCEELKEX
//
DD
DISP=SHR,DSN=CEE.SCEELKED
//
DD
DISP=SHR,DSN=CEE.SCEECPP
//
DD
DISP=SHR,DSN=CBC.SCLBSID
//SYSLIB1
DD
DISP=SHR,
//
DSN=hqual.SIXMEXP
//SYSLIB2
DD
DISP=SHR,DSN=&SYSUID..BATCH.OBJ
//SYSLMOD
DD
DISP=SHR,DSN=&SYSUID..BATCH.LOAD
//SYSDEFSD DD
DUMMY
//SYSPRINT DD
SYSOUT=A
//SYSDEFSD DD
DUMMY
//OPTS
DD
DUMMY
//SYSLIN
DD
DUMMY
//
PEND
//*
//* Compile SAX2CNT
//*
//COMPILE EXEC PROC=CPPPROC,
//
MEMBER=SAX2CNT,
//
SRCLIB=&SYSUID..BATCH.CPP
//OPTS
DD *
LANGLVL(EXTENDED)
NOSEARCH SEARCH(
/usr/lpp/ixm/IBM/xml4c-5_7/include/,
//'userid.BATCH.+',
//'CEE.SCEEH.+',
//'CBC.SCLBH.+')
117
C++ and XML
DEFINE(OS390=1)
DEFINE(_OPEN_THREADS=1)
DEFINE(_XOPEN_SOURCE_EXTENDED=1)
/*
//*
//* Compile SAX2HND
//*
//COMPILE EXEC PROC=CPPPROC,
//
MEMBER=SAX2HND,
//
SRCLIB=&SYSUID..BATCH.CPP
//OPTS
DD *
LANGLVL(EXTENDED)
NOSEARCH SEARCH(
/usr/lpp/ixm/IBM/xml4c-5_7/include/,
//'userid.BATCH.+',
//'CEE.SCEEH.+',
//'CBC.SCLBH.+')
DEFINE(OS390=1)
DEFINE(_OPEN_THREADS=1)
DEFINE(_XOPEN_SOURCE_EXTENDED=1)
/*
//*
//* Compile SAX2CNTH
//*
//COMPILE EXEC PROC=CPPPROC,
//
MEMBER=SAX2CNTH,
//
SRCLIB=&SYSUID..BATCH.HPP
//OPTS
DD *
LANGLVL(EXTENDED)
NOSEARCH SEARCH(
/usr/lpp/ixm/IBM/xml4c-5_7/include/,
//'userid.BATCH.+',
//'CEE.SCEEH.+',
//'CBC.SCLBH.+')
DEFINE(OS390=1)
DEFINE(_OPEN_THREADS=1)
DEFINE(_XOPEN_SOURCE_EXTENDED=1)
/*
//*
//* Compile SAX2HNDH
//*
//COMPILE EXEC PROC=CPPPROC,
//
MEMBER=SAX2HNDH,
//
SRCLIB=&SYSUID..BATCH.HPP
//OPTS
DD *
LANGLVL(EXTENDED)
NOSEARCH SEARCH(
/usr/lpp/ixm/IBM/xml4c-5_7/include/,
//'userid.BATCH.+',
//'CEE.SCEEH.+',
//'CBC.SCLBH.+')
DEFINE(OS390=1)
DEFINE(_OPEN_THREADS=1)
DEFINE(_XOPEN_SOURCE_EXTENDED=1)
118
C++ and XML
/*
//*
//* Build the module
//*
//LINK
EXEC PROC=CPPLINK
//OPTS
DD
*
AMODE=31,RMODE=ANY
DYNAM=DLL,ALIASES=NO,UPCASE=NO
LIST=NO,MAP=NO,XREF=NO,
REUS=RENT,EDIT=YES,AC=0,CALL=YES,CASE=MIXED
/*
//SYSLIN DD
*
INCLUDE SYSLIB(IOSTREAM)
INCLUDE SYSLIB(COMPLEX)
INCLUDE SYSLIB1(IXM4C57X)
INCLUDE SYSLIB2(SAX2CNT)
INCLUDE SYSLIB2(SAX2HND)
INCLUDE SYSLIB2(SAX2CNTH)
INCLUDE SYSLIB2(SAX2HNDH)
ENTRY
CEESTART
NAME
SAX2CNT(R) RC=0
/*
//*
//* Execute the module
//*
//GO
EXEC PGM=&MODULE,
// PARM=('////usr/lpp/ixm/IBM/xml4c-5_7/samples/data/pe
//
rsonal.xml')
//STEPLIB DD
DISP=SHR,DSN=&SYSUID..BATCH.LOAD
//
DD
DISP=SHR,DSN=&IXMLOAD
The SAX2CNT module should execute with a return code of 0 and produce this single line
********************************* Top of Data *********************************
/samples/data/personal.xml: 46 ms (37 elems, 12 attrs, 134 spaces, 134 chars)
******************************** Bottom of Data *******************************
Note
Even with the sources in Z/OS libraries the build still needs to include elements that are stored in the USS.
See the OPTS contents in the Compilations. Note also the input data can reside in the USS.
119
C++ and XML
5. How to use the z/OS specific parser classes
The XML Toolkit for z/OS brings z/OS specific parser classes that can be used in place of the regular Xerces classes. These examples can be found in the zsamples subfolder of the toolkit: zDOMCount,
zDOMPrint, zDOMPParse, zMemParse, zSAX2Count and zSAX2Print.
The z/OS specific classes all start with the letter 'z'. For example zSAX2XMLReader class.
This section covers these topics:
• Generate zsamples in the USS
• Execute in the USS
• Generate zsamples in Z/OS
• Execute zsamples in Z/OS
120
C++ and XML
5.1. Generate zsamples
If you generated the samples set of examples, not much is needed to generate that second set but adjusting
the input and output locations.
• Copy the zsamples programs to your private area
cp -r $XERCESCROOT/zsamples $XERCESCOUT
• Add the zsamples folder to your path:
export PATH=/a/userid/xml/zsamples:$PATH
• Create zsamples.bat in /a/userid/xml/zsamples by copying samples.bat and change the cd command:
echo
cd
"* Changing current directory "
$XERCESCOUT/zsamples
• Run zsamples.bat
Notes
• We copied the entire zsamples folder to our private zsamples area. In addition to the sources the zsamples
folder contains Makefiles and other files that are necessary for the generation. Copying only the sources
and executing the script would fail to generate the modules.
• The modules are stored in /a/userid/bin
121
C++ and XML
5.2. Execute zsamples in the USS
Adjust your path to include the zsamples folder. Then the modules can be executed individually. For
example:
zMemParse -v=never
A script such as the below one can be created to facilitate the testing of the examples
#
#
#
#
#
#
#
#
passing arguments to a shell script
$*
$@
$0
$n
$#
=
=
=
=
=
the
the
the
the
the
complete string passed to the script
sequence of strings the argument is made of
script name
nth string
number of strings passed to the script.
if test "$1" = ""
then
echo ' '
echo '============================================ '
echo '
'
echo '
XML Toolkit for z/OS
'
echo '
'
echo 'Usage:
'
echo '
xsamples.bat executes the application '
echo 'whose name is passed as an argument.
'
echo '
'
echo 'The program must be available in the path.
'
echo '
'
echo 'Each application processes the same xml
'
echo 'input:
'
echo '
'
echo $XERCESCROOT/samples/data/personal.xml
echo '============================================ '
echo ' '
echo 'The following applications are available:
'
echo ' '
echo 'zDOMCount -p $XERCESCROOT/samples/data/personal.xml
echo ' Counts the elements, attributes, spaces and
'
echo ' characters in an XML file
'
echo '
'
echo ' use option -p for print
'
echo ' use option -v=always to trigger the validation
'
echo '
'
echo 'ZDOMPrint $XERCESCROOT/samples/data/personal.xml '
echo ' Parses the xml input file, then calls DOMWrite
echo ' to print the elements.
'
echo '
'
122
'
'
C++ and XML
echo
echo
echo
echo
echo
echo
echo
echo
echo
echo
echo
echo
echo
echo
echo
echo
echo
echo
'ZDOMPParse $XERCESCROOT/samples/data/personal.xml '
'
'
'zMemParse -v=always
'
' This program uses the SAX Parser to parse a memory
'
' buffer containing XML statements, and reports the number'
' of elements and attributes found.
'
'
'
'zPParse
-v=always $XERCESCROOT/samples/data/personal.xml'
' Progressive parsing
'
'
'
'zSAX2Count $XERCESCROOT/samples/data/personal.xml
'
' Counts the elements, attributes, spaces and characters '
' in an XML file
'
'
'
'zSAX2Print $XERCESCROOT/samples/data/personal.xml '
' Parses an XML file and prints it out.
'
'
'
'
'
#
# Cannot continue the if test on several lines!
#
elif test "$1" = "zDOMCount" -o "$1" = "zDOMPrint"
then
echo '***'
echo '*** xsamples.bat is starting the execution of '$1
echo '***'
$1 -v=never $XERCESCROOT/samples/data/personal.xml
echo
echo
echo
elif test
then
echo
echo
echo
'***'
'*** Program has ended an returned control to xsamples.bat'
'***'
"$1" = "zPParse"
-o "$1" = "zDOMPParse"
'***'
'*** xsamples.bat is starting the execution of '$1
'***'
$1 -v=never $XERCESCROOT/samples/data/personal.xml
echo
echo
echo
elif test
then
echo
echo
echo
'***'
'*** Program has ended an returned control to xsamples.bat'
'***'
"$1" = "zSAX2Count" -o "$1" = "zSAX2Print"
'***'
'*** xsamples.bat is starting the execution of '$1
'***'
$1 -v=never $XERCESCROOT/samples/data/personal.xml
echo '***'
echo '*** Program has ended an returned control to xsamples.bat'
echo '***'
123
C++ and XML
elif test
then
echo
echo
echo
$1
"$1" = "zMemParse"
'***'
'*** xsamples.bat is starting the execution of '$1
'***'
-v=never
echo '***'
echo '*** Program has ended an returned control to xsamples.bat'
echo '***'
else
echo '*** '
echo '*** Program name not recognized:' $1
echo '*** '
fi
124
C++ and XML
5.3. Generate zsamples in Z/OS
After the configuration has been established in the USS it is fairly straight forward to generate the Z/OS
load modules.
Set these variables if they arent't already:
export LOADMOD=userid.SAMPLES.rel.LOAD
export LOADEXP=hlq.SIXMEXP
export CXX=c++
export CXXFLAGS="-2"
export OS390_BIT64=1 (if running 64-bit support examples)
export OS390_XPLINK=1 (if running 31-bit XPLINK support examples)
export _CXX_CXXSUFFIX=cpp
export _CXX_XSUFFIX_HOST=SIXMEXP
export _CSS_CCMODE=1
Run gmake
gmake
These loadmodules are stored into your Z/OS load library: ZDOMCONT, ZDOMPPAR, ZDOMPRNT,
ZMEMPARS, ZPPARSE, ZSAX2CNT and ZSAX2PRT.
125
C++ and XML
5.4. Execute zsamples in Z/OS
An example of executing ZMEMPARS in a batch job in Z/OS is given below.
//useridU JOB accnt,'Run module',CLASS=A Sure
//*
//* ----------------------------------------------------------------//* This job executes a module that was built by gmake from a cpp
//* source in the USS.
//*
//* HFS is case sensitive - use Caps on
//* ----------------------------------------------------------------//*
//
SET STEPLIB=userid.SAMPLES.REL.LOAD
//
SET IXMLOAD=hql.SIXMLOD1
//
SET ZSAMPLE=ZMEMPARS
//*
//* ----------------------------------------------------------------//*
- Run the example #1
//* ----------------------------------------------------------------//RUN01
EXEC PGM=&ZSAMPLE
//STEPLIB DD
DISP=SHR,DSN=&STEPLIB
//
DD
DISP=SHR,DSN=&IXMLOAD
/*
The job dynamically allocates a sysout named SYS00001 and writes these lines to it
Finished parsing the memory buffer containing the following XML statements:
<?xml version='1.0' encoding='ibm-1047-s390'?>
<!DOCTYPE company [
<!ELEMENT company
(product,category,developedAt)>
<!ELEMENT product
(#PCDATA)>
<!ELEMENT category
(#PCDATA)>
<!ATTLIST category idea CDATA #IMPLIED>
<!ELEMENT developedAt (#PCDATA)>
]>
<company>
<product>XML4C</product>
<category idea='great'>XML Parsing Tools</category>
<developedAt>
IBM Center for Java Technology, Silicon Valley, Cupertino, CA
</developedAt>
</company>
Parsing took 51 ms (4 elements, 1 attributes, 0 spaces, 111 characters).
126
C++ and XML
6. How to use the XSLT Processor, C++ Edition
In this section we explain how to prepare and run the IBM's examples about the XSLT processing. The
setup is very much like the setup we walked through in the prior sections in this chapter.
The xslt examples are located in the samples subfolder of the xslt installation folder, whose path is usually
like usr/lpp/ixm/IBM/xslt4c-1_xx.
They are: CompileStylesheet, SimpleTransform,UseStylesheetParam, DocumentBuilder, SimpleXPathAPI, XPathWrapper, ExternalFunction, SimpleXPathCAPI, XalanTransform, StreamTransform,
XalanTransfomerCallback, ParseSourceWrappers, TraceListen, SerializeNodeSet and TransformToXercesDOM.
Most examples in that set expect an input foo.xml, use a sytlesheet foo.xsl and produce a foo.out output.
This section covers these topics:
• Generate the xslt examples
• Execute in the USS
• Generate xslt examples in Z/OS
• Execute in Z/OS
Note, no configure utility needs to be executed prior to gmake.
127
C++ and XML
6.1. Generate the xslt examples in the USS
Set up your environment. These variables comme in addition to the variables that are required for the XML
parsing and that were detailed in the prior sections.
These export commands can be issued manually or made permanent in the .profile.
export XALANCROOT=/sys/usr/lpp/ixm/IBM/xslt4c-1_11
export XALANCOUT=/a/userid/xml
Copy the examples to a private area
mkdir /a/userid/xml/xslsamples
cp -r $XALANCROOT/samples $XALANCOUT/xslsamples
Every example comes in a folder under the same name as the program (in the below example CompileStylesheet). Most of these examples need one or more 'foo' input files, that are available in a subfolder in the folder that contains the program. As CompileStylesheet has the most extensive list of foo files
included, we copy these to our private area and can use them with all examples.
mkdir /a/userid/xml/foo
cp $XALANCROOT/samples/CompileStylesheet/foo*
128
/a/userid/xml/foo
C++ and XML
6.2. Execute the xslt examples in the USS
In order to execute one of these examples
• Go to the a/userid/foo folder
• Adjust the path
export PATH=$XALANCOUT/bin:$PATH
Note
The 'foo' files, including the foo.out output from these examples, are in ASCII. In order to best view these
files you can copy them to a sequential data set in Z/OS, start a TSO/ISPF edit session in ASCII mode or
issue the primary command 'SOURCE ASCII'' within the edit session.
As suggested by the reading of the .xsl file this stylesheet intructs the Xalan transformer to select the 'doc'
elements and change them into 'out' elements. Also the xml header is added the encoding attribute
Here's the contents of the foo.xml file
File Edit Edit_Settings Menu Utilities Compilers Test Help
------------------------------------------------------------------------------EDIT
userid.XML.FOOXML
Columns 00001 00072
****** ***************************** Top of Data ******************************
000001 <?xml version="1.0"?> <doc>Hello</doc>
****** **************************** Bottom of Data ****************************
Here's the contents of the foo.xsl file in a TSO/ISPF edit session. The three lines we reproduced below
are actually a single line of 216 characters.
File Edit Edit_Settings Menu Utilities Compilers Test Help
------------------------------------------------------------------------------EDIT
userid.XML.FOOXSL
Columns 00001 00072
****** ***************************** Top of Data ******************************
000001 <?xml version="1.0"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999
****** **************************** Bottom of Data ****************************
//
EDIT
userid.XML.FOOXSL
Columns 00073 00144
****** ***************************** Top of Data ******************************
000001 /XSL/Transform" version="1.0">
<xsl:template match="doc">
<out><xs
****** **************************** Bottom of Data ****************************
//
File
Edit
Edit_Settings
Menu
129
Utilities
Compilers
Test
Help
C++ and XML
------------------------------------------------------------------------------EDIT
userid.XML.FOOXSL
Columns 00145 00216
****** ***************************** Top of Data ******************************
000001 l:value-of select="."/></out>
</xsl:template> </xsl:stylesheet>
****** **************************** Bottom of Data ****************************
Below is the contents of the foo.out file in a TSO/ISPf edit session
File Edit Edit_Settings Menu Utilities Compilers Test Help
------------------------------------------------------------------------------EDIT
userid.XML.FOOOUT
Columns 00001 00072
****** ***************************** Top of Data ******************************
000001 <?xml version="1.0" encoding="UTF-8"?><out>Hello</out>
****** **************************** Bottom of Data ****************************
130
C++ and XML
6.3. Generate the xslt examples to Z/OS
Once the configuration has been run in the USS it is fairly straight forward to generate the Z/OS load
modules.
Set these variables if they arent't already:
export LOADMOD=userid.SAMPLES.rel.LOAD
export LOADEXP=hlq.SIXMEXP
export CXX=c++
export CXXFLAGS="-2"
export OS390_BIT64=1 (if running 64-bit support examples)
export OS390_XPLINK=1 (if running 31-bit XPLINK support examples)
export _CXX_CXXSUFFIX=cpp
export _CXX_XSUFFIX_HOST=SIXMEXP
export _CSS_CCMODE=1
Run gmake
gmake
131
C++ and XML
6.4. Execute the xslt examples in Z/OS
The following loadmodules should have been generated: CMPSTYSH, DOCBLDR, EXTERNFN, SERNODES, SMPLTRNS, STRMTRNS, SXPTAPI, SXPTCAPI, TRACELSN, TRTXDOM, USESTYSH,
XALNTCLB, XALNTRNS and XPATHWRP.
Use a JCL like the below to execute in Z/OS
//useridX JOB Accnt,'xslt example',CLASS=A
//*
//* ----------------------------------------------------------------//* This job executes a module that gmake generated from a source
//* program in the USS (XML toolkit for z/OS).
//*
//* HFS is case sensitive - use Caps on
//* ----------------------------------------------------------------//*
//
SET STEPLIB=userid.SAMPLES.REL.LOAD
//
SET IXMLOAD=hlq.SIXMLOD1
//
SET EXAMPLE=TRACELSN
//*
//* ----------------------------------------------------------------//*
- Run this example
//* ----------------------------------------------------------------//RUN01
EXEC PGM=&EXAMPLE,
// PARM= ':-tt'
//*
//STEPLIB DD
DISP=SHR,DSN=&STEPLIB
//
DD
DISP=SHR,DSN=&IXMLOAD
Note
Most examples do not execute well in Z/OS as there's no way to indicate where the foo files are located.
An exception is the TRACELSN program, which does not expect any input and does not create any output.
132
C++ and XML
6.5. Fully generate a xslt example in Z/OS
In the prior section the build of the Z/OS load modules was performed in the USS. In this section we
see how an application can be entirely generated in a Z/OS batch job. Consider the SimpleTransform.cpp
example that can be found in the USS. It is a simple program that includes the XalanMemoryManager.hpp.
These sources will be copied to a Z/OS library and the loadmodule generated and executed in Z/OS.
The SimpleTransform.cpp sources processes three files whose names are hardcoded and makes mandatory
to execute with the current directory containing these files. We'll change that so the program can execute
in a Z/OS environment as well.
Copy and edit as follows
• Copy SimpleTransform.cpp as SMPLTRNS member to the CPP library
cp SimpleTransform.cpp "//'userid.BATCH.CPP(SMPLTRNS)'"
• Copy XalanMemoryManager.hpp as XALANMMI to the HPP library
cp XalanMemoryManager.hpp "//'userid.BATCH.HPP(XALANMMI)'"
• Edit the SMPLTRNS member and change the includes to reference XALANMMI instead of XalanMemoryManager. Change the program so that SMLPTRNS program accepts three parameters.
#include <xalanc/Include/PlatformDefinitions.hpp>
#if defined(XALAN_CLASSIC_IOSTREAMS)
#include <iostream.h>
#else
#include <iostream>
#endif
#include <xercesc/util/PlatformUtils.hpp>
#include <xalanc/XalanTransformer/XalanTransformer.hpp>
#include "XALANMMI.hpp"
.....
/*
* Add the support of file name parameters in order to execute
* in Z/OS.
* - parm #1 XML Input file
* - parm #2 XSL Input file
* - parm #3
Output file
*/
int
133
C++ and XML
main(
int argc,
char* argv[])
{
XALAN_USING_STD(cerr)
XALAN_USING_STD(endl)
int theResult = -1;
char xmlFile[120];
char xslFile[120];
char outFile[120];
char* returnString;
if (argc != 4)
{
cerr << "Error: Incorrect number of parameters: " << argc
<< endl
<< endl;
cerr << "Usage: SimpleTransform input.xml input.xsl output"
<< endl
<< endl;
}
else
// Don't verify the parameters.
returnString = strncpy(xmlFile,argv[1],120);
returnString = strncpy(xslFile,argv[2],120);
returnString = strncpy(outFile,argv[3],120);
cerr << "SMPLTRNS program will invoke the Xalan transformer "
<< "using the following files:" << endl
<< "\n Input : " << xmlFile
<< "\n
: " << xslFile
<< "\n Output : " << outFile << endl << endl;
try
{
XALAN_USING_XERCES(XMLPlatformUtils)
XALAN_USING_XERCES(XMLUni)
XALAN_USING_XALAN(XalanTransformer)
XalanMemoryManagerImpl memoryManager;
#ifdef XALAN_USE_ICU
.....
#endif
// Call the static initializer for Xerces.
XMLPlatformUtils::Initialize(
XMLUni::fgXercescDefaultLocale,
0,
0,
&memoryManager );
134
C++ and XML
// Initialize Xalan.
XalanTransformer::initialize( memoryManager );
{
// Create a XalanTransformer.
XalanTransformer theXalanTransformer( memoryManager );
// Pass user's parameters to the transformer
theResult = theXalanTransformer.transform(xmlFile, xslFile, outFile);
if(theResult != 0)
{
cerr << "SimpleTransform Error: \n" << theXalanTransformer.getLastError();
<< endl
<< endl;
}
}
.....
Use a JCL such as the below one to generate the SMPLTRNS loadmodule and execute it in Z/OS.
//useridX JOB accnt,'XML CPP',CLASS=A,MSGCLASS=A,
//*
//
SET
MODULE=SMPLTRNS
//
SET
IXMLOAD=hqual.SIXMLOD1
//*
//JOBLIB
DD DISP=SHR,DSN=CEE.SCEERUN
//
DD DISP=SHR,DSN=CEE.SCEERUN2
//
DD DISP=SHR,DSN=CBC.SCCNCMP
//*
//* --------------------------------------------------------------//* CPPPROC procedure invokes the CPP compiler
//* --------------------------------------------------------------//CPPPROC PROC MEMBER=,
//
SRCLIB=
//COMPILE EXEC PGM=CCNDRVR,PARM='/CXX OPTFILE(DD:OPTS),OBJ,LIST'
//SYSLIN
DD DISP=SHR,DSN=&SYSUID..BATCH.OBJ(&MEMBER)
//SYSPRINT DD SYSOUT=A
//SYSIN
DD DISP=SHR,DSN=&SRCLIB(&MEMBER)
//SYSUT1
DD DUMMY
//OPTS
DD DUMMY
//
PEND
//* --------------------------------------------------------------//* CPPLINK procedure invokes the linker in a CPP context
//* --------------------------------------------------------------//CPPLINK
PROC
//LINK
EXEC PGM=IEWL,PARM='OPTIONS=OPTS'
//SYSLIB
DD
DISP=SHR,DSN=CEE.SCEELKEX
//
DD
DISP=SHR,DSN=CEE.SCEELKED
//
DD
DISP=SHR,DSN=CEE.SCEECPP
//
DD
DISP=SHR,DSN=CEE.SCEELIB
135
C++ and XML
//
DD
DISP=SHR,DSN=CBC.SCLBSID
//SYSLIB1
DD
DISP=SHR,
//
DSN=hqual.SIXMEXP
//SYSLIB2
DD
DISP=SHR,DSN=&SYSUID..BATCH.OBJ
//SYSLMOD
DD
DISP=SHR,DSN=&SYSUID..BATCH.LOAD
//SYSDEFSD DD
DUMMY
//SYSPRINT DD
SYSOUT=A
//SYSDEFSD DD
DUMMY
//OPTS
DD
DUMMY
//SYSLIN
DD
DUMMY
//
PEND
//*
//* Compile SMPLTRNS
//*
//COMPILE EXEC PROC=CPPPROC,
//
MEMBER=SMPLTRNS,
//
SRCLIB=&SYSUID..BATCH.CPP
//OPTS
DD *
LANGLVL(EXTENDED)
NOSEARCH SEARCH(
/usr/lpp/ixm/IBM/xml4c-5_7/include/,
/usr/lpp/ixm/IBM/xslt4c-1_11/include/,
/usr/lpp/ixm/IBM/xslt4c-1_11/include/xalanc/Include/,
/usr/lpp/ixm/IBM/xslt4c-1_11/include/xalanc/XSLT/,
//'userid.BATCH.+',
//'CEE.SCEEH.+',
//'CBC.SCLBH.+')
DEFINE(OS390=1)
DEFINE(_OPEN_THREADS=1)
DEFINE(_XOPEN_SOURCE_EXTENDED=1)
/*
//*
//* Build the module
//*
//LINK
EXEC PROC=CPPLINK
//OPTS
DD
*
AMODE=31,RMODE=ANY
DYNAM=DLL,ALIASES=NO,UPCASE=NO
LIST=NO,MAP=NO,XREF=NO,
REUS=RENT,EDIT=YES,AC=0,CALL=YES,CASE=MIXED
/*
//SYSLIN DD
*
INCLUDE SYSLIB(IOSTREAM)
INCLUDE SYSLIB(COMPLEX)
INCLUDE SYSLIB(C128N)
INCLUDE SYSLIB1(IXM4C57X)
INCLUDE SYSLIB1(IXMLC21X)
INCLUDE SYSLIB2(SMPLTRNS)
ENTRY
CEESTART
NAME
SMPLTRNS(R) RC=0
/*
//*
//* Execute the module
//*
136
C++ and XML
//GO
EXEC PGM=&MODULE,
// PARM=('//a/userid/xml/foo/foo.xml /a/userid/xml/foo/foo.xsl //XML.T
//
ESTOUT')
//STEPLIB DD
DISP=SHR,DSN=&SYSUID..BATCH.LOAD
//
DD
DISP=SHR,DSN=&IXMLOAD
SMPLTRNS dynamically allocates a sysout and writes a report such as:
********************************* Top of Data **********************************
SMPLTRNS program will invoke the Xalan transformer using the following files:
Input
: /a/userid/xml/foo/foo.xml
: /a/userid/xml/foo/foo.xsl
Output : //XML.TESTOUT
******************************** Bottom of Data ********************************
SMPLTRNS dynamically allocates and creates the Z/OS data set 'XML.TESTOUT'. As the output is in
ASCII use the 'SOURCE ASCII' command in the TSO/ISPF editor to reformat the output so that it is
readable
****** ***************************** Top of Data ******************************
000001 <?xml version="1.0" encoding="UTF-8"?><out>Hello</out>
****** **************************** Bottom of Data ****************************
137
C++ and XML
6.6. Execute the Xalan transformer directly
The Xalan transformer may be invoked in the USS using line commands such as
• Xalan -o foo.out foo.xml foo.xsl
In the above command
• Xalan (with an uppercase 'X') must be available in the PATH
• -o means an output is written to the file whose name follows
• foo.out, foo.xml and foo.xsl are very likely path/name expressions unless they all reside in the current
directory.
Enter Xalan with no parameter to display the usage message
Xalan version 1.11.0.
Xerces version 2.6.0.
Usage: Xalan Ýoptions¨ source stylesheet
Options:
-a
Use xml-stylesheet PI, not the 'stylesheet' argument
-e encoding
Force the specified encoding for the output.
-i integer
Indent the specified amount.
-m
Omit the META tag in HTML output.
-o filename
Write output to the specified file.
-p name expression
Sets a stylesheet parameter.
-t
Display timing information.
-u
Disable escaping of URLs in HTML output.
-?
Display this message.
-v
Validates source documents.
A dash as the 'source' argument reads from stdin.
('-' cannot be used for both arguments.)
The transformer may also be executed in a Z/OS batch job as shown below. The OUTFILE, INXML and
INXSL allocations may reference files in the USS as well as data sets in Z/OS.
//useridX JOB accnt,'Xalan',CLASS=A
//*
//* ----------------------------------------------------------------//* This job invokes the XALAN transformer.
//* - IXMXAQ21
64-bit executable
//* - IXMXAL21
31-bit executable
//*
//* HFS is case sensitive - use Caps on
//* ----------------------------------------------------------------//*
//
SET IXMLOAD=hql.SIXMLOD1
//*
//RUN01
EXEC PGM=IXMXAQ21,
//
PARM='/-e ibm-1047-s390 -o DD:OUTFILE DD:INXML DD:INXSL'
138
C++ and XML
//STEPLIB DD
DISP=SHR,DSN=&IXMLOAD
//*
//* Alternative syntaxes can be used to allocate a z/os file input
//*
//* PARM='///DD:XMLDATA(PERSONAL)'
//* PARM='DD:XMLDATA(PERSONAL)'
//*
//* PARM='"//''userid.XML.DATA(PERSONAL)''"'
//* PARM='"//XML.DATA(PERSONAL)"'
(automatic prefixation)
//*
//OUTFILE DD
SYSOUT=*
//INXML
DD
PATH='/a/userid/xml/foo/foo.xml',PATHOPTS=ORDONLY
//INXSL
DD
PATH='/a/userid/xml/foo/foo.xsl',PATHOPTS=ORDONLY
139
C++ and XML
6.7. Execute the test XSLT utility
Along with the XALAN transformer a test XSLT transformer is provided. It offers additional options over
the regular XALAN utility.
Prior to executing the test XSLT transformer make sure these variables are set:
• XALANCROOT
• XERCESCROOT
• The PATH must include the $XALANCROOT/bin location
• The LIBPATH must include the $XALANCROOT/lib and $XERCESCROOT/lib locations
The test XSLT utility can be executed in a number of ways
• Type testXSLT with no option in the command line and enter options at the keyboard
• Type testXSLT -h in order to display the full list of options
• Type testXSLT in the command line, followed by the options necessary to perform the desired task
testXSLT [-option [-option] ... ]
The test XSLT transformer may also be executed in a Z/OS batch job
//userid$ JOB accnt,'Xalan',CLASS=A
//*
//* ----------------------------------------------------------------//* This job invokes the XALAN transformer and prints a trace to a
//* dynamically allocated sysout.
//* - IXMTSQ21
64-bit executable
//* - IXMTST21
31-bit executable
//*
//* HFS is case sensitive - use Caps on
//* ----------------------------------------------------------------//*
//
SET IXMLOAD=hql.SIXMLOD1
//*
//RUN01
EXEC PGM=IXMTSQ21,
//
PARM='/-ttc -out DD:OUTFILE -in DD:INXML -xsl DD:INXSL'
//STEPLIB DD
DISP=SHR,DSN=&IXMLOAD
//OUTFILE DD
SYSOUT=*
//INXML
DD
PATH='/a/userid/xml/foo/foo.xml',PATHOPTS=ORDONLY
//INXSL
DD
PATH='/a/userid/xml/foo/foo.xsl',PATHOPTS=ORDONLY
Here's the full list of options that the test XLST utility accepts
140
C++ and XML
TestXSLT options:
Options are case-sensitive.
[-? Shows this message.]
[-h Shows this message.]
[-in <source URL> (If not specified, stdin is used.)]
[-xsl <stylesheet URL>]
[-out <output file>]
[-v Show version information only.]
[-qc Quiet pattern conflicts warnings.]
[-q Use quiet mode.]
[-indent n Controls how many spaces to indent. (default is 0)]
[-validate Controls whether validation occurs. Validation is off by default.]
[-tt Trace the templates as they are being called.]
[-tg Trace each generation event.]
[-ts Trace each selection event.]
[-ttc Trace the template children as they are being processed.]
[-xml Use XML formatter.]
[-text Use Text formatter.]
[-html Use HTML formatter.]
[-dom Use DOM formatter. Generates a DOM instance, then formats XML for output.]
[-xst Use source tree formatter. Generates an instance of the default source tre
[-param name expression Sets a stylesheet parameter.]
[-xd Use Xerces DOM instead of Xalan source tree.]
[-de Disable built-in extension functions.]
The following option is valid only with -html.
[-noindent Turns off HTML indenting.
The following option is valid only with -xml.
[-nh Don't generate the XML declaration.]
141
C++ and XML
7. How to call the XML Toolkit from a Cobol
program
This section shows an example of building an application that consists of a Cobol main program that
invokes the XML toolkit in C subroutines. The C routines will reside in a DLL. As a Cobol program cannot
call a C DLL directly, an intermediate program is required.
The application is structured as detailed below.
• SPFEXML program is the Cobol main program.
• A1CCDLGTprogram is the cpp intermediate program
• SAXPRSE and SAXHNDL are the cpp sources
• SAXPRSEH and SAXHNDLH are the hpp includes
• personal-schema.xml and personal.xsd are the test inputs for the SPFEXML program
For the convenience's sake the SPFEXML, A1CCDLGT, SAXPRSE and SAXHNDL programs will be
stored in the CPP library and SAXPRSEH and SAXHNDLH includes will be stored in the HPP library.
142
C++ and XML
7.1. Set up the test files for the SPFEXML application
It is recommended to copy the personal-schema.xml and personal.xsd files from the IBM location to a
private location. In the below commands we assume the variable $XERCESCROOT contains the path to
the IBM's examples and /a/userid/xml/samples is the target location.
cp $XERCESCROOT/data/samples/personal-schema.xml
/a/userid/xml/samples/personal-schema.xml
cp $XERCESCROOT/data/samples/personal.xsd
/a/userid/xml/samples/personal.xsd
Create in the userid.BATCH.XML library a member named INVALID with the below contents. Although
apparently correct these XML lines do not conform to the personal.xsd specification
<?xml version="1.0" encoding="ibm-1140"?>
<personnel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation=
'/a/userid/xml/samples/personal.xsd'>
<person id="Big.Boss">
<name><family>Boss</family> <given>Big</given></name>
<email>chief@foo.com</email>
<link subordinates="one.worker two.worker"/>
</person>
<person id="one.worker">
<name><family>Worker</family> <given>One</given></name>
<link manager="Big.Boss"/>
<email>one@foo.com</email>
</person>
<person id="two.worker">
<name><family>Worker</family> <given>Two</given></name>
<email>two@foo.com</email>
<link manager="Big.Boss"/>
<phone>+1.123.555.1234</phone>
</person>
</personnel>
143
C++ and XML
7.2. The SPFEXML cobol program
This program does the following:
• Calls A1CCDLGT program to get the entry point of the validate_parse function in SAXPRSE DLL
• Invokes parse_validate against the file name hardcoded in fileName field
• Invokes parse_validate against a resource that is referenced by its DD name: INVALID
Process pgmname(longmixed),noexportall,outdd(sysprint),nodynam
Title 'COBOL program SPFEXML.'
IDENTIFICATION DIVISION.
PROGRAM-ID
'SAXParseFrontEnd'.
AUTHOR.
PATRICE.
*REMARKS. This program is an example published by IBM
*
in the XML Toolkit's user guide, Appendix B
*
Note the nodynam compilation option.
DATE-WRITTEN. 20 Jan 2015.
DATE-COMPILED.
SECURITY.
Confidentiality level.
DATA DIVISION.
* ---------------------------------------------------*
WORKING-STORAGE SECTION.
* ---------------------------------------------------WORKING-STORAGE SECTION.
01 fileName
pic x(80)
value z'/a/userid/xml/samples/personal-schema.xml'.
01 invalidFile
pic x(12)
value z'DD:INVALID'.
01 rc
pic s9(9) comp-5.
01 fnlen
pic 99.
* ** The below fields for the C DLL support.
01 DLL-INFO.
03 DLL-LOADMOD-NAME PIC X(12)
value spaces.
03 DLL-PROGRAM-NAME PIC X(160) value spaces.
03 DLL-PROGRAM-HANDLE
usage pointer.
01 DLL-RC
PIC S9(9) binary.
01 DLL-PROGRAM-PTR
PROCEDURE-POINTER.
01 DLL-STATUS
PIC X(1)
value 'N'.
88 DLL-LOADED
value 'Y'.
88 DLL-NOT-LOADED
value 'N'.
01 Retvalue
PIC S9(9) comp.
/
* ---------------------------------------------------*
PROCEDURE DIVISION.
* ---------------------------------------------------PROCEDURE DIVISION.
MAIN-SECTION.
* Call A1CCDLGT utility to retrieve parse_valide function
IF DLL-NOT-LOADED THEN
MOVE z'SAXPRSE'
144
to DLL-LOADMOD-NAME
C++ and XML
MOVE z'parse_validate' to DLL-PROGRAM-NAME
CALL 'A1CCDLGT' using by reference DLL-INFO
by reference DLL-RC
IF DLL-RC = 0 THEN
SET DLL-LOADED to true
ELSE
DISPLAY 'A1CCLDGT failed with Rc=' DLL-RC
MOVE 16 to RETURN-CODE
STOP RUN
END-IF
END-IF
SET DLL-PROGRAM-PTR to DLL-PROGRAM-HANDLE
* Try a valid file.
* ** Call 'parse_validate'
Call
DLL-PROGRAM-PTR
using by value address of fileName
returning rc
Move 0 to tally
Inspect fileName
tallying tally for characters before x'00'
If rc = 0
Display '"' fileName(1:tally) '" is valid.'
Else
Display '"' fileName(1:tally) '" is invalid!'
End-if
* Try now a well-formed but invalid file, accessed
* by DDName INVALID.
* ** Call 'parse_validate'
Call
DLL-PROGRAM-PTR
using by value address of invalidFile
returning rc
Move 0 to tally
Inspect invalidFile
tallying tally for characters before x'00'
If rc = 0
Display '"' invalidFile(1:tally)
'" was supposedly invalid (?).'
Move 8 to return-code
Else
Display '"' invalidFile(1:tally)
'" is invalid as expected.'
End-if
Goback.
End program 'SAXParseFrontEnd'.
145
C++ and XML
146
C++ and XML
7.3. The A1CCDLGT program
A1CCDLGT is a generic program that can be used to retrieve the entry point of a function within a DLL
and pass the address back to a Cobol caller. A1CCDLGT must be linked together with the Cobol main
program.
/*
* A1CCDLGT is part of an example in the IBM's MAINFRAME-DLLS.doc
* document.
*
* A cobol program cannot invoke a C/C++ DLL directly it can only
* do that through an intermediate program such as A1CCDLGT.
*
* A1CCDLGT is expecting a DLL module name and a function name
* within the DLL. The entry point of the function is returned
* to the caller that can use it run the DLL.
*
* Note the pragma linkage.
*
*/
#include <stdio.h>
#include <dll.h>
#pragma linkage (A1CCDLGT,COBOL)
typedef struct dll_lm {
char
dll_loadmod_name[12];
char
dll_func_name[160];
void
(*fptr) (void);
} dll_lm;
void A1CCDLGT (dll_lm *dll, int *rc)
{
dllhandle *handle;
void (*fptr1) (void);
*rc = 0;
/* Load the DLL using the C runtime services */
handle = dllload(dll->dll_loadmod_name);
if (handle == NULL) {
perror("A1CCDLGT failed on call to load DLL.\n");
*rc = 1;
return;
}
/* Load succeeded, get its entry point
*/
fptr1 = (void (*) (void))
dllqueryfn(handle,dll->dll_func_name);
if (fptr1 == NULL) {
perror("A1CCDLGT failed on retrieving function.\n");
*rc = 2;
return;
}
147
C++ and XML
/* Function has been located, return its entry point */
printf("A1CCDLGT returned the pointer of function %s in ddl %s",
dll->dll_func_name, dll->dll_loadmod_name, "\n");
dll->fptr = fptr1;
return;
}
148
C++ and XML
7.4. The SAXPRSE program
This program invokes the SAXParser parser against the xmlFilePath file object
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
*
http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* $Log: SAXParse.cpp,v $
* Created by Patrice Cotte per the XML Toolkit user's guide Appendix B
*
* The xercesc includes are part of the XML toolkit currently at:
* $XERCESCROOT/include/xercesc
*
* xercesc contains subfolders sax, util, parsers, dom, internal
*
zparsers, validators, framework, sax2
*/
// --------------------------------------------------------------------------// Includes
// --------------------------------------------------------------------------#include <xercesc/parsers/SAXParser.hpp>
#include <xercesc/util/OutOfMemoryException.hpp>
#include "SAXPRSEH.hpp"
#include "stdio.h"
// --------------------------------------------------------------------------// Function prototypes
// -----------------------------------------------------------------------extern "C"
{
int parse_validate(char * xmlFilePath);
}
// -----------------------------------------------------------------------// Parse_validate initializes the parser environment and does a single
// parse of the XML document specified in the parameter list.
149
C++ and XML
// It terminates and cleans up the environment before exiting.
// -----------------------------------------------------------------------int parse_validate(char * xmlFilePath)
{
bool error_occurred = false;
bool warning_occurred = false;
unsigned long duration;
SAXParser * parser;
SAXParseHandlers * handler;
// Initialize the XML4C2 system
try
{
XMLPlatformUtils::Initialize();
}
catch (const OutOfMemoryException&)
{
XERCES_STD_QUALIFIER cerr << "OutOfMemoryException "
<< "during initialization! "
<< XERCES_STD_QUALIFIER endl;
return 8;
}
catch (const XMLException& toCatch)
{
XERCES_STD_QUALIFIER cerr << "Error during initialization! :\n"
<< StrX(toCatch.getMessage()) << XERCES_STD_QUALIFIER endl;
return 1;
}
catch (...)
{
XERCES_STD_QUALIFIER cerr << "Error during initialization! :"
<< XERCES_STD_QUALIFIER endl;
return 8;
}
//
// Create a SAX parser object and set options.
//
parser = new SAXParser;
parser->setDoNamespaces(true);
parser->setDoSchema(true);
parser->setValidationSchemaFullChecking(true);
parser->setValidationScheme(SAXParser::Val_Auto);
handler = new SAXParseHandlers();
parser->setErrorHandler(handler);
//
//
//
Kick off parse catching exceptions.
150
C++ and XML
try
{
const unsigned long startMillis =
XMLPlatformUtils:: getCurrentMillis();
parser->parse(xmlFilePath);
const unsigned long endMillis =
XMLPlatformUtils:: getCurrentMillis();
duration = endMillis - startMillis;
}
catch (const OutOfMemoryException&)
{
XERCES_STD_QUALIFIER cerr << "OutOfMemoryException" << XERCES_STD_QUALIFIER en
error_occurred = true;
}
catch (const XMLException& e)
{
XERCES_STD_QUALIFIER cerr << "\nError during parsing: \n"
<< StrX(e.getMessage())
<< XERCES_STD_QUALIFIER endl;
error_occurred = true;
}
catch (...)
{
XERCES_STD_QUALIFIER cerr << "Error during parsing: \n"
<< XERCES_STD_QUALIFIER endl;
error_occurred = true;
}
if (handler->getSawErrors()) {
error_occurred = true;
}
if (handler->getSawWarnings()) {
warning_occurred = true;
}
if (!error_occurred) {
XERCES_STD_QUALIFIER cout << xmlFilePath << ": "
<< duration << " MS "
<< XERCES_STD_QUALIFIER endl;
}
//
// Delete the parser itself.
//
delete handler;
delete parser;
Must be done prior to calling Terminate, below.
// And call the termination method
XMLPlatformUtils::Terminate();
if (error_occurred)
return 8;
else if (warning_occurred)
return 4;
else return 0;
}
151
C++ and XML
152
C++ and XML
7.5. The SAXHNDL program
This program is the error handler for the SAXPRSE program
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
*
http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* $Log: SAXParseHandlers.cpp,v $
*
* Created by
Patrice Cotte
January 21, 2015
* Reason
Cobol/SAX example per the XML Toolkit User's guide
*
Appendix B
*
*/
// --------------------------------------------------------------------------// Includes
// --------------------------------------------------------------------------#include <xercesc/sax/SAXParseException.hpp>
#include <xercesc/util/XMLString.hpp>
#include <xercesc/util/XMLUniDefs.hpp>
#include "SAXPRSEH.hpp"
// --------------------------------------------------------------------------// SAXParseHandlers: Constructors and Destructor
// --------------------------------------------------------------------------SAXParseHandlers::SAXParseHandlers() :
fSawErrors(false)
,fSawWarnings(false)
{
}
SAXParseHandlers::~SAXParseHandlers()
{
}
153
C++ and XML
// --------------------------------------------------------------------------// SAXParseHandlers: Overrides of the SAX Errorhandler interface
// --------------------------------------------------------------------------void SAXParseHandlers::error(const SAXParseException& e)
{
fSawErrors = true;
XERCES_STD_QUALIFIER cerr << "\n Error at (file "
<< StrX(e.getSystemId())
<< ", line " << e.getLineNumber()
<< ", char " << e.getColumnNumber()
<< ") : "
<< StrX(e.getMessage())
<< XERCES_STD_QUALIFIER endl;
}
void SAXParseHandlers::fatalError(const SAXParseException& e)
{
fSawErrors = true;
XERCES_STD_QUALIFIER cerr << "\n Fatal error at (file "
<< StrX(e.getSystemId())
<< ", line " << e.getLineNumber()
<< ", char " << e.getColumnNumber()
<< ") : "
<< StrX(e.getMessage())
<< XERCES_STD_QUALIFIER endl;
}
void SAXParseHandlers::warning(const SAXParseException& e)
{
fSawWarnings = true;
XERCES_STD_QUALIFIER cerr << "\n Warning at (file "
<< StrX(e.getSystemId())
<< ", line " << e.getLineNumber()
<< ", char " << e.getColumnNumber()
<< ") : "
<< StrX(e.getMessage())
<< XERCES_STD_QUALIFIER endl;
}
void SAXParseHandlers::resetDocument()
{
fSawWarnings = false;
fSawErrors
= false;
}
154
C++ and XML
7.6. The SAXPRSEH include
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
*
http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* $Log: SAXParse.hpp,v $
*
* Created by
Patrice Cotte
Janauary 25, 2015
* Reason
Cobol/SAX example per the XML Toolkit user's guide
*
Appendix B
*/
// --------------------------------------------------------------------------// Includes for all the program files to see
// --------------------------------------------------------------------------#include <string.h>
#include <stdlib.h>
#if defined(XERCES_NEW_IOSTREAMS)
#include <iostream>
#else
#include <iostream.h>
#endif
#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/parsers/SAXParser.hpp>
#include "SAXHNDLH.hpp"
// --------------------------------------------------------------------------// This is a simple class that lets us do easy (though not terribly efficient)
// trancoding of XMLCh data to local code page for display.
// --------------------------------------------------------------------------class StrX
{
public :
// ----------------------------------------------------------------------// Constructors and Destructor
155
C++ and XML
// ----------------------------------------------------------------------StrX(const XMLCh* const toTranscode)
{
// Call the private transcoding method
fLocalForm = XMLString::transcode(toTranscode);
}
~StrX()
{
XMLString::release(&fLocalForm);
}
// ----------------------------------------------------------------------// Getter methods
// ----------------------------------------------------------------------const char* localForm() const
{
return fLocalForm;
}
private :
// ----------------------------------------------------------------------// Private data members
//
// fLocalForm
//
This is the local code page form of the string.
// ----------------------------------------------------------------------char*
fLocalForm;
};
inline XERCES_STD_QUALIFIER ostream& operator<<(XERCES_STD_QUALIFIER ostream&
target, const StrX& toDump)
{
target << toDump.localForm();
return target;
}
156
C++ and XML
7.7. The SAXHNDLH include
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
*
http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* $Log: SAXParseHandlers.hpp,v $
*
* Created by
Patrice Cotte
* Reason
Cobol/SAX example
*
*
*/
#include
January 21, 2015
per the XML Toolkit User's guide
Appendix B
<xercesc/sax/HandlerBase.hpp>
XERCES_CPP_NAMESPACE_USE
class SAXParseHandlers : public HandlerBase
{
public:
// ---------------------------------------------------------------------// Constructor and Destructor
// ---------------------------------------------------------------------SAXParseHandlers();
~SAXParseHandlers();
// ---------------------------------------------------------------------// Handlers for the SAX ErrorHandler interface
// ---------------------------------------------------------------------void warning(const SAXParseException& exception);
void error(const SAXParseException& exception);
void fatalError(const SAXParseException& exception);
// ---------------------------------------------------------------------// Implementations of the SAX ErrorHandler interface
157
C++ and XML
// ---------------------------------------------------------------------bool getSawErrors() const
{
return fSawErrors;
}
bool getSawWarnings() const
{
return fSawWarnings;
}
void resetDocument();
private:
bool fSawErrors;
bool fSawWarnings;
};
158
C++ and XML
7.8. The JCL
The JCl includes three procedures in-stream. These procedures might be stored in a procedure library
(proclib).
//useridX JOB accnt,'COB XML Toolkit',CLASS=A,MSGCLASS=A
//*
//
SET
MODULE=SPFEXML
//
SET
IXMLOAD=hqual.SIXMLOD1
//*
//JOBLIB
DD DISP=SHR,DSN=CEE.SCEERUN
//
DD DISP=SHR,DSN=CEE.SCEERUN2
//
DD DISP=SHR,DSN=CBC.SCCNCMP
//*
//* --------------------------------------------------------------//* CPPPROC procedure invokes the CPP compiler
//* --------------------------------------------------------------//CPPPROC PROC MEMBER=,
//
SRCLIB=,
//
CPARM='CXX OPTFILE(DD:OPTS),OBJ'
//CPPCOMP EXEC PGM=CCNDRVR,
//
PARM='/&CPARM'
//SYSLIN
DD DISP=SHR,DSN=&SYSUID..BATCH.OBJ(&MEMBER)
//SYSPRINT DD SYSOUT=A
//SYSOUT
DD SYSOUT=A
//SYSERR
DD SYSOUT=A
//SYSIN
DD DISP=SHR,DSN=&SRCLIB(&MEMBER)
//SYSUT1
DD DUMMY
//OPTS
DD DUMMY
//
PEND
//* --------------------------------------------------------------//* CPPLINK procedure invokes the linker in a CPP context
//* --------------------------------------------------------------//CPPLINK
PROC
//LINK
EXEC PGM=IEWL,PARM='OPTIONS=OPTS'
//SYSLIB
DD
DISP=SHR,DSN=CEE.SCEELKEX
//
DD
DISP=SHR,DSN=CEE.SCEELKED
//
DD
DISP=SHR,DSN=CEE.SCEECPP
//
DD
DISP=SHR,DSN=CBC.SCLBSID
//SYSLIB1
DD
DISP=SHR,
//
DSN=hqual.SIXMEXP
//SYSLIB2
DD
DISP=SHR,DSN=&SYSUID..BATCH.OBJ
//SYSLMOD
DD
DISP=SHR,DSN=&SYSUID..BATCH.LOAD
//SYSDEFSD DD
DUMMY
//SYSPRINT DD
SYSOUT=A
//SYSDEFSD DD
DUMMY
//OPTS
DD
DUMMY
//SYSLIN
DD
DUMMY
//
PEND
//* --------------------------------------------------------------//*
Compile and Link Cobol procedure
//* ---------------------------------------------------------------
159
C++ and XML
//COBLPROC PROC MEMBER=,
MEMBER NAME
//
MODULE=,
MODULE NAME
//
COBPRM1='APOST,DYNAM,LIB,LIST,MAP,OPT,RENT',
//
COBPRM2='NOSSR,NOSEQ,TRUNC(BIN),XREF',
//
LNKPARM='RENT,REUS,LET'
//COBCOMP EXEC PGM=IGYCRCTL,REGION=4M,
//
PARM=(&COBPRM1,
//
&COBPRM2)
//STEPLIB DD DSN=hqualcob.SIGYCOMP,DISP=SHR
//SYSPRINT DD SYSOUT=A
//SYSLIB
DD DSN=hqualcob.SIGYSAMP,DISP=SHR
//SYSLIN
DD DSNAME=&&LOADSET,UNIT=VIO,DISP=(NEW,PASS),
//
SPACE=(CYL,(1,1))
//SYSIN
DD DSN=&SYSUID..BATCH.CPP(&MEMBER),DISP=SHR
//SYSUT1
DD UNIT=VIO,SPACE=(CYL,(1,1))
//SYSUT2
DD UNIT=VIO,SPACE=(CYL,(1,1))
//SYSUT3
DD UNIT=VIO,SPACE=(CYL,(1,1))
//SYSUT4
DD UNIT=VIO,SPACE=(CYL,(1,1))
//SYSUT5
DD UNIT=VIO,SPACE=(CYL,(1,1))
//SYSUT6
DD UNIT=VIO,SPACE=(CYL,(1,1))
//SYSUT7
DD UNIT=VIO,SPACE=(CYL,(1,1))
//SYSUT8
DD UNIT=VIO,SPACE=(CYL,(1,1))
//*
//COBLINK EXEC PGM=IEWL,
//
PARM='LIST,MAP,&LNKPARM',
//
COND=(5,LT,COBCOMP),REGION=4M
//SYSPRINT DD SYSOUT=A
//SYSLIB
DD DSN=CEE.SCEELKED,DISP=SHR
//
DD DSN=hqualcob.SIGYCOMP,DISP=SHR
//SYSUT1
DD UNIT=VIO,DCB=BLKSIZE=1024,SPACE=(CYL,(1,1))
//SYSLMOD DD DSN=&SYSUID..BATCH.LOAD(&MODULE),DISP=SHR
//SYSLIN
DD DSNAME=&&LOADSET,DISP=(OLD,DELETE)
//
DD DDNAME=SYSIN
//
PEND
//*
//* Compile SAXPRSE
//*
//COMPSAX EXEC PROC=CPPPROC,
//
MEMBER=SAXPRSE,
//
SRCLIB=&SYSUID..BATCH.CPP
//OPTS
DD *
DLL,EXPORTALL
LANGLVL(EXTENDED)
LIST,OFFSET,SOURCE,XREF
NOSEARCH SEARCH(
/usr/lpp/ixm/IBM/xml4c-5_7/include/,
//'userid.BATCH.+',
//'CEE.SCEEH.+',
//'CBC.SCLBH.+')
DEFINE(OS390=1)
DEFINE(_OPEN_THREADS=1)
DEFINE(_XOPEN_SOURCE_EXTENDED=1)
/*
//*
160
C++ and XML
//* Compile SAXHNDL
//*
//COMPSAXH EXEC PROC=CPPPROC,
//
MEMBER=SAXHNDL,
//
SRCLIB=&SYSUID..BATCH.CPP
//OPTS
DD *
LANGLVL(EXTENDED)
LIST,OFFSET,SOURCE,XREF
NOSEARCH SEARCH(
/usr/lpp/ixm/IBM/xml4c-5_7/include/,
//'userid.BATCH.+',
//'CEE.SCEEH.+',
//'CBC.SCLBH.+')
DEFINE(OS390=1)
DEFINE(_OPEN_THREADS=1)
DEFINE(_XOPEN_SOURCE_EXTENDED=1)
/*
//* Build the module - LIST=YES and/or MAP=YES and/or XREF=YES
//*
to get the details of the linked module
//*
- DYNAM=DLL lets the binder
//*
* Write IMPORTS to the SUBDEFSD (side-deck)
//*
* Create IEWBLIT (Loader info table)
//*
* Create IEWBCIE (Compiler Import/export tbl)
//*
This option should be used when the module is a
//*
DLL or will load DLLs.
//LINKSAX EXEC PROC=CPPLINK
//OPTS
DD
*
AMODE=31,RMODE=ANY
DYNAM=DLL,ALIASES=NO,UPCASE=NO
LIST=NO,MAP=YES,XREF=YES
REUS=RENT,EDIT=YES,AC=0,CALL=YES,CASE=MIXED
/*
//SYSLIN DD
*
INCLUDE SYSLIB(IOSTREAM)
INCLUDE SYSLIB1(IXM4C57X)
INCLUDE SYSLIB2(SAXHNDL)
INCLUDE SYSLIB2(SAXPRSE)
ENTRY
CEESTART
NAME
SAXPRSE(R) RC=0
/*
//*
//* Compile and link the A1CCDLGT intermediate program
//*
//COMPA1CC EXEC PROC=CPPPROC,
//
MEMBER=A1CCDLGT,
//
SRCLIB=&SYSUID..BATCH.CPP,
//
CPARM='OPTFILE(DD:OPTS)'
//OPTS
DD
*
NOSEARCH SEARCH('CEE.SCEEH.+') NOOPT SO OBJ DLL RENT LONGNAME
/*
//LINKA1CC EXEC PROC=CPPLINK
//OPTS
DD
*
AMODE=31,MAP
RENT,DYNAM=DLL
161
C++ and XML
CASE=MIXED
/*
//SYSLIN DD
*
INCLUDE SYSLIB(IOSTREAM)
INCLUDE SYSLIB2(A1CCDLGT)
NAME
A1CCDLGT(R) RC=0
/*
//*
//* Compile and link the Cobol main program SPFEXML
//*
//COMPSPFE
EXEC PROC=COBLPROC,MODULE='SPFEXML',
//
MEMBER='SPFEXML'
//COBLINK.SYSLIB DD DISP=SHR,DSN=CEE.SCEELKED
//
DD DISP=SHR,DSN=SYS1.LINKLIB
//
DD DISP=SHR,DSN=&SYSUID..BATCH.LOAD
//*
//* Execute the module
//*
//GO
EXEC PGM=&MODULE
//STEPLIB DD
DISP=SHR,DSN=&SYSUID..BATCH.LOAD
//
DD
DISP=SHR,DSN=&IXMLOAD
//INVALID DD
DISP=SHR,DSN=&SYSUID..BATCH.XML(INVALID)
//CEEDUMP DD
SYSOUT=*
162
C++ and XML
7.9. The outputs produced by the SPFEXML application
These outputs should be obtained:
********************************* Top of Data **********************************
"/a/userid/xml/samples/personal-schema.xml" is valid.
"DD:INVALID" is invalid as expected.
******************************** Bottom of Data ********************************
********************************* Top of Data **********************************
Error at (file DD:INVALID, line 1, char 1210) : Element 'email' is not valid for
content model: '((name,email,url),link)'
Error at (file DD:INVALID, line 1, char 1691) : Unknown element 'phone'
Error at (file DD:INVALID, line 1, char 1770) : Element 'phone' is not valid for
content model: '((name,email,url),link)'
******************************** Bottom of Data ********************************
********************************* Top of Data **********************************
A1CCDLGT returned the pointer of function parse_validate in ddl SAXPRSE
******************************** Bottom of Data ********************************
163
Chapter 4. Conclusion
If you tried all the examples in this book - and I have no doubt you did! - you really deserve congratulations!
I'd like to thank you for your time and the interest you found in this book.
Many interesting and various topics in the programming across different environments in Z/OS and using
different languages have been covered. Your vision is now wider and you have taken several steps to the
modern world.
164
Download