|
Java Interface |
||||||
As well as the Batch interface, Cobol2Xml can be called from a JVM language (Java, Kotlin, Groovy, JRuby etc). This program interface offers mor options (e.g. Array checks, complicated RecordSelection etc). Once again these interface programs can be generated from the RecordEditor CodeGen Option.
You can run the Cobol <==> Xml process via the following methods of Cobol2Xml class:
Cobol2Xml.newCobol2Xml(CobolCopybook) Cobol2Xml.newCobol2Xml(CobolCopybookInputStream, Copybook name) Cobol2Xml.newCb2Xml2Xml(Cb2xmlCopybook) Cobol2Xml.newCb2Xml2Xml(Cb2xmlCopybookInputStream, CopybookName)
A sample call:
1 2 Cobol2Xml.newCobol2Xml(opts.cobolCopybook) 3 .setFont(opts.font) 4 .setFileOrganization(opts.fileOrganisation) 5 .setDialect(opts.dialect) 6 .setDropCopybookNameFromFields(opts.dropCopybookName) 7 .setXmlMainElement(opts.mainXmlTag) 8 .cobol2xml(opts.inputFile, opts.outputFile); 9
When using Multiple record (Cobol-Data ==>> Xml) you must set-up record selection (so the program know which record it is reading/writng !!):
1 2 3 Cobol2GroupXml.newCobol2Xml(copybookFileName) 4 .setFileOrganization(Constants.IO_BIN_TEXT) 5 .setDialect(ICopybookDialects.FMT_INTEL) 6 .setSplitCopybook(CopybookLoader.SPLIT_01_LEVEL) 7 .setRecordSelection("PO-Record", newFieldSelection("Record-Type","H1")) 8 .setRecordSelection("Product-Record", newFieldSelection("Record-Type","D1")) 9 .setRecordSelection("Location-Record", newFieldSelection("Record-Type","S1")) 10 .cobol2xml(new FileInputStream(dataFileName), os); 11
or
1 2 3 Cobol2GroupXml.newCobol2Xml(copybookFileName) 4 .setFileOrganization(Constants.IO_BIN_TEXT) 5 .setDialect(ICopybookDialects.FMT_INTEL) 6 .setSplitCopybook(CopybookLoader.SPLIT_01_LEVEL) 7 .setRecordPositionCode("Header-Record", Options.RP_FIRST_RECORD_IN_FILE) 8 .setRecordPositionCode("Detail-Record", Options.RP_MIDDLE_RECORDS) 9 .setRecordPositionCode("Trailer-Record", Options.RP_LAST_RECORD_IN_FILE) 10 .cobol2xml(new FileInputStream(dataFileName), os); 11
In the above code, newFieldSelection is defined as:
20 private static ExternalFieldSelection newFieldSelection(String fieldName, String value) { 21 ExternalFieldSelection r = new ExternalFieldSelection(fieldName, value); 22 r.setCaseSensitive(false); 23 return r; 24 } 25
Using one of the JVM scripting languages (Groovy, Java-Script (jjs), Jython, JReuby, kotlin etc) offers much greater flexibity and possibly better performance than the Batch interface (Data2Xml, Xml2Data).
To make it easier to call Cobol2Xml from JVM scripting languages, a static variable JR_CONSTANTS to the Cobol2Xml class:
20 /* ---------------------------------------------------------------------- 21 * 22 * Cobol Dialects: 23 */ 24 public final int FMT_MAINFRAME = ICopybookDialects.FMT_MAINFRAME; 25 public final int FMT_FUJITSU = ICopybookDialects.FMT_FUJITSU; 26 public final int FMT_BIG_ENDIAN = ICopybookDialects.FMT_BIG_ENDIAN; 27 public final int FMT_FS2000 = ICopybookDialects.FMT_FS2000; 28 29 public final int FMT_FS2000_BE = ICopybookDialects.FMT_FS2000_BE; 30 public final int FMT_MAINFRAME_COMMA_DECIMAL = ICopybookDialects.FMT_MAINFRAME_COMMA_DECIMAL; 31 public final int FMT_FUJITSU_COMMA_DECIMAL = ICopybookDialects.FMT_FUJITSU_COMMA_DECIMAL; 32 33 public final int FMT_GNU_COBOL = ICopybookDialects.FMT_OPEN_COBOL_BE; 34 public final int FMT_GNU_COBOL_MVS = ICopybookDialects.FMT_GNU_COBOL_MVS; 35 public final int FMT_GNU_COBOL_MF = ICopybookDialects.FMT_GNU_COBOL_MF; 36 37 public final int FMT_GNU_COBOL_BE = ICopybookDialects.FMT_GNU_COBOL; 38 public final int FMT_GNU_COBOL_BE_MVS = ICopybookDialects.FMT_OPEN_COBOL_MVS_BE; 39 public final int FMT_GNU_COBOL_BE_MF = ICopybookDialects.FMT_OC_MICRO_FOCUS_BE; 40 41 /* ------------------------------------------------------------------------- 42 * 43 * Cobol Copybook split options 44 */ 45 public final int SPLIT_NONE = ICobolSplitOptions.SPLIT_NONE; 46 public final int SPLIT_REDEFINE = ICobolSplitOptions.SPLIT_REDEFINE; 47 public final int SPLIT_01_LEVEL = ICobolSplitOptions.SPLIT_01_LEVEL; 48 public final int SPLIT_HIGHEST_REPEATING = ICobolSplitOptions.SPLIT_HIGHEST_REPEATING; 49 50 /* ------------------------------------------------------------------------ 51 * 52 * IO Options 53 */ 54 public final int IO_STANDARD_TEXT_FILE = Constants.IO_STANDARD_TEXT_FILE; 55 56 public final int IO_FIXED_LENGTH_RECORDS = Constants.IO_FIXED_LENGTH_RECORDS; 57 public final int IO_BINARY_IBM_4680 = Constants.IO_BINARY_IBM_4680; 58 public final int IO_VB = Constants.IO_VB; 59 public final int IO_VB_DUMP = Constants.IO_VB_DUMP; 60 public final int IO_VB_FUJITSU = Constants.IO_VB_FUJITSU; 61 public final int IO_VB_OPEN_COBOL = Constants.IO_VB_OPEN_COBOL; 62 public final int IO_BIN_TEXT = Constants.IO_BIN_TEXT; 63 public final int IO_FIXED_LENGTH_CHAR = Constants.IO_FIXED_LENGTH_CHAR ; 64 65 public final int IO_CONTINOUS_NO_LINE_MARKER= Constants.IO_CONTINOUS_NO_LINE_MARKER; 66 67 public final int IO_CSV = Constants.IO_CSV; 68 public final int IO_BIN_CSV = Constants.IO_BIN_CSV; 69 public final int IO_UNICODE_CSV = Constants.IO_UNICODE_CSV; 70 71 public final int IO_CSV_NAME_1ST_LINE = Constants.IO_CSV_NAME_1ST_LINE ; 72 public final int IO_BIN_CSV_NAME_1ST_LINE = Constants.IO_BIN_CSV_NAME_1ST_LINE; 73 public final int IO_UNICODE_CSV_NAME_1ST_LINE = Constants.IO_UNICODE_CSV_NAME_1ST_LINE ; 74 75 public final int IO_NAME_1ST_LINE = Constants.IO_NAME_1ST_LINE; 76 public final int IO_BIN_NAME_1ST_LINE = Constants.IO_BIN_NAME_1ST_LINE ; 77 public final int IO_UNICODE_NAME_1ST_LINE = Constants.IO_UNICODE_NAME_1ST_LINE; 78 79 public final int IO_STANDARD_UNICODE_TEXT_FIL = Constants.IO_STANDARD_UNICODE_TEXT_FILE ; 80 81 public final int IO_UNICODE_TEXT = Constants.IO_UNICODE_TEXT; 82 public final int IO_FIXED_LENGTH = Constants.IO_FIXED_LENGTH; 83 public final int IO_TEXT_LINE = Constants.IO_TEXT_LINE; 84 85 86 /* ------------------------------------------------------------------------------ 87 * 88 * Option to reformat Cobol names when converting to other languages 89 * 90 */ 91 public final int RO_LEAVE_ASIS = IReformatFieldNames.RO_LEAVE_ASIS; 92 public final int RO_MINUS_TO_UNDERSCORE = IReformatFieldNames.RO_UNDERSCORE; 93 public final int RO_CAMEL_CASE = IReformatFieldNames.RO_CAMEL_CASE; 94
Java 8 comes with a Java-Script interpreter (jjs) which can be used to call Cobol2Xml / Xml2Cobol programs.
All the javascript examples start with:
11 var Cobol2Xml = Java.type("net.sf.JRecord.cbl2xml.Cobol2Xml") 12 var constants = Cobol2Xml.JR_CONSTANTS
Basically to convert a Cobol-Data file to Xml, you do:
18 var dtar020Xml= Cobol2Xml.newCobol2Xml("DTAR020.cbl") 19 .setFileOrganization(constants.IO_FIXED_LENGTH_RECORDS) // Fixed Length Record 20 .setDialect(constants.FMT_MAINFRAME) // Mainframe Cobol (the Default) 21 .setFont("cp037"); // US EBCDIC 22 23 dtar020Xml .cobol2xml("in/DTAR020.bin", "out/DTAR020_JS.xml"); // Convert a DTAR020 file to Xml 24 dtar020Xml .xml2Cobol("out/DTAR020_JS.xml", "out/DTAR020_JS.bin"); // Convert the Xml file back to a Binary Cobol file 25
The following Java-Script will convert a Multi-Record file into Xml
65 Cobol2Xml .newCobol2Xml("amsPoDownload.cbl") 66 // Set Cobol Copybook Options 67 .setFileOrganization(constants.IO_UNICODE_TEXT) 68 .setDialect(constants.FMT_FUJITSU) 69 .setSplitCopybook(constants.SPLIT_01_LEVEL) 70 71 // Tell JRecord how determine which record is which by Testing the Record-Type field 72 .setRecordSelection("PO-Record", Cobol2Xml.newFieldSelection("Record-Type","H1")) 73 .setRecordSelection("Product-Record", Cobol2Xml.newFieldSelection("Record-Type","D1")) 74 .setRecordSelection("Location-Record", Cobol2Xml.newFieldSelection("Record-Type","S1")) 75 76 // Define parent - child relationships between Records 77 .setRecordParent("Product-Record", "PO-Record") // The parent of Product-Record is PO-Record 78 .setRecordParent("Location-Record", "Product-Record") 79 80 // Convert file to Xml 81 .cobol2xml("in/Ams_PODownload_20041231.txt", "out/Ams_PODownload_20041231_js_tree.xml"); 82
Calling Cbl2Xml in Groovy is the same as calling it from Java-Script.
18 def dtar020Xml= Cobol2Xml.newCobol2Xml("DTAR020.cbl") 19 .setFileOrganization(constants.IO_FIXED_LENGTH_RECORDS) // Fixed Length Record 20 .setDialect(constants.FMT_MAINFRAME) // Mainframe Cobol (the Default) 21 .setFont("cp037"); // US EBCDIC 22 23 dtar020Xml .cobol2xml("in/DTAR020.bin", "out/DTAR020_Groovy.xml"); // Convert a DTAR020 file to Xml 24 dtar020Xml .xml2Cobol("out/DTAR020_Groovy.xml", "out/DTAR020_Groovy.bin"); // Convert the Xml file back to a Binary Cobol file 25
To convert a multi-record file:
65 Cobol2Xml .newCobol2Xml("amsPoDownload.cbl") 66 // Set Cobol Copybook Options 67 .setFileOrganization(constants.IO_UNICODE_TEXT) 68 .setDialect(constants.FMT_FUJITSU) 69 .setSplitCopybook(constants.SPLIT_01_LEVEL) 70 71 // Tell JRecord how determine which record is which by Testing the Record-Type field 72 .setRecordSelection("PO-Record", Cobol2Xml.newFieldSelection("Record-Type","H1")) 73 .setRecordSelection("Product-Record", Cobol2Xml.newFieldSelection("Record-Type","D1")) 74 .setRecordSelection("Location-Record", Cobol2Xml.newFieldSelection("Record-Type","S1")) 75 76 // Define parent - child relationships between Records 77 .setRecordParent("Product-Record", "PO-Record") // The parent of Product-Record is PO-Record 78 .setRecordParent("Location-Record", "Product-Record") 79 80 // Convert file to Xml 81 .cobol2xml("in/Ams_PODownload_20041231.txt", "out/Ams_PODownload_20041231_Groovy_tree.xml"); 82
For a single record file like:
9 03 DTAR020-KCODE-STORE-KEY. 10 05 DTAR020-KEYCODE-NO Pic X(08). 11 05 DTAR020-STORE-NO PIC S9(03) COMP-3. 12 03 DTAR020-DATE PIC S9(07) COMP-3. 13 03 DTAR020-DEPT-NO PIC S9(03) COMP-3. 14 03 DTAR020-QTY-SOLD PIC S9(9) COMP-3. 15 03 DTAR020-SALE-PRICE PIC S9(9)V99 COMP-3. 16
The bat file to the conversion to Xml
../lib/Cobol2Xml.bat ^ -cobol DTAR020.cbl -font cp037 -fileOrganisation FixedWidth ^ -input in/DTAR020.bin ^ -output out/DTAR020_A.xml
The Groovy code to convert it to Xml is
12 def dtar020Xml= Cobol2Xml.newCobol2Xml("DTAR020.cbl") 13 .setFileOrganization(constants.IO_FIXED_LENGTH_RECORDS) 14 .setDialect(constants.FMT_MAINFRAME) 15 .setFont("cp037"); 16
Generated Xml is:
1 <?xml version="1.0" encoding="UTF-8"?> 2 <copybook> 3 <Line> 4 <DTAR020-KCODE-STORE-KEY> 5 <DTAR020-KEYCODE-NO>69684558</DTAR020-KEYCODE-NO> 6 <DTAR020-STORE-NO>20</DTAR020-STORE-NO> 7 </DTAR020-KCODE-STORE-KEY> 8 <DTAR020-DATE>40118</DTAR020-DATE> 9 <DTAR020-DEPT-NO>280</DTAR020-DEPT-NO> 10 <DTAR020-QTY-SOLD>1</DTAR020-QTY-SOLD> 11 <DTAR020-SALE-PRICE>19.00</DTAR020-SALE-PRICE> 12 </Line> 13 <Line> 14 <DTAR020-KCODE-STORE-KEY> 15 <DTAR020-KEYCODE-NO>69684558</DTAR020-KEYCODE-NO> 16 <DTAR020-STORE-NO>20</DTAR020-STORE-NO> 17 </DTAR020-KCODE-STORE-KEY> 18 <DTAR020-DATE>40118</DTAR020-DATE> 19 <DTAR020-DEPT-NO>280</DTAR020-DEPT-NO> 20 <DTAR020-QTY-SOLD>-1</DTAR020-QTY-SOLD> 21 <DTAR020-SALE-PRICE>-19.00</DTAR020-SALE-PRICE> 22 </Line> 23 <Line> 24 .... 25 </Line> 26 <Line> 27 .... 28 </Line> 29 .... 30 </copybook>
With Multi-Record files, you must define how to determine what type of record it is. There are other options to consider as well.
The COBOL copybook for a multi-record copybook would look like:
4 01 PO-Record. 5 03 Record-Type Pic X(2). 6 03 Sequence-Number Pic 99v999. 7 03 Vendor Pic 9(10). 8 03 PO Pic 9(12). 9 ... 10 11 01 Product-Record. 12 03 Record-Type pic xx. 13 03 Pack-Qty Pic 9(5)V9999. 14 ... 15 16 01 Location-Record. 17 03 Record-Type pic xx. 18 03 location occurs 10. 19 05 DC-Number pic 9(4). 20 05 Pack-Quantity pic 9(8).
in Groovy you would do:
13 Cobol2Xml .newCobol2Xml("amsPoDownload.cbl") 14 // Cobol Options 15 .setFileOrganization(constants.IO_UNICODE_TEXT) 16 .setSplitCopybook(constants.SPLIT_01_LEVEL) // Split the Cobol Copybook on 01 levels 17 .setFont("UTF-8") // It is a good idea to set the Character-set 18 19 // Tell JRecord how determine which record is which by Testing the Record-Type field 20 .setRecordSelection("PO-Record", Cobol2Xml.newFieldSelection("Record-Type","H1")) // Record-Type='H1' 21 .setRecordSelection("Product-Record", Cobol2Xml.newFieldSelection("Record-Type","D1")) // Record-Type='D1' 22 .setRecordSelection("Location-Record", Cobol2Xml.newFieldSelection("Record-Type","S1")) 23 24 .cobol2xml("in/Ams_PODownload_20041231.txt", "out/Ams_PODownload_20041231_Groovy_flat.xml");
And finally the Xml will look like:
2 <CobolData> 3 <PO-Record> 4 <Record-Type>H1</Record-Type> 5 ... 6 </PO-Record> 7 <Product-Record> 8 <Record-Type>D1</Record-Type> 9 ... 10 </Product-Record> 11 <Location-Record> 12 <Record-Type>S1</Record-Type> 13 ... 14 </Location-Record> 15 <Product-Record> 16 <Record-Type>D1</Record-Type> 17 ... 18 </Product-Record> 19 <Location-Record> 20 <Record-Type>S1</Record-Type> 21 ... 22 </Location-Record> 23 <Location-Record> 24 <Record-Type>S1</Record-Type> 25 ... 26 </Location-Record> 27 ... 28 </CobolData>
You can define a Record Hierachy using the setRecordParent method:
11 Cobol2Xml .newCobol2Xml("amsPoDownload.cbl") 12 // Set Cobol Copybook Options 13 .setFileOrganization(constants.IO_UNICODE_TEXT) 14 .setDialect(constants.FMT_FUJITSU) 15 .setSplitCopybook(constants.SPLIT_01_LEVEL) 16 17 // Tell JRecord how determine which record is which by Testing the Record-Type field 18 .setRecordSelection("PO-Record", Cobol2Xml.newFieldSelection("Record-Type","H1")) 19 .setRecordSelection("Product-Record", Cobol2Xml.newFieldSelection("Record-Type","D1")) 20 .setRecordSelection("Location-Record", Cobol2Xml.newFieldSelection("Record-Type","S1")) 21 22 // Define parent - child relationships between Records 23 .setRecordParent("Product-Record", "PO-Record") // The parent of Product-Record is PO-Record 24 .setRecordParent("Location-Record", "Product-Record")25 26 // Convert file to Xml 27 .cobol2xml("in/Ams_PODownload_20041231.txt", "out/Ams_PODownload_20041231_Groovy_tree.xml");
In the Generated Xml, the Location-Record tag is Nested inside the Product-Record which is intern nested inside the PO-Record:
2 <CobolData> 3 <PO-Record> 4 ... 5 <Product-Record> 6 ... 7 <Location-Record> 8 ... 9 </Location-Record> 10 </Product-Record> 11 <Product-Record> 12 ... 13 <Location-Record> 14 .... 15 </Product-Record> 16 <Product-Record> 17 ... 18 <Location-Record> 19 ... 20 </Location-Record> 21 <Location-Record> 22 ... 23 </Location-Record> 24 </Product-Record> 25 .... 26 </PO-Record> 27 <PO-Record> 28 ... 29 </PO-Record> 30 ... 31 </CobolData>
CobolToCsv at SourceForge | Download Page | Forums |