Purpose: This document contains example code showing how to parse a JDF (Job Definition Format) XML document into DB2 Physical Files.
Physical Files:
*-------------------------------------------------------------------------
* @Name - JDFCFG
* @Author - Aaron Bartell
* @Desc - Holds configuration info.
*-------------------------------------------------------------------------
A R JDFCFGR TEXT('JDF Config')
A XMLDIR 128A COLHDG('XML Dir')
A ACHDIR 128A COLHDG('Archive Dir')
A DEBUG 1A COLHDG('Debug T/F')
*-------------------------------------------------------------------------
* @Name - JDFLOG
* @Author - Aaron Bartell
* @Desc - Holds log info.
*-------------------------------------------------------------------------
A R JDFLOGR TEXT('JDF Log')
A PID 15P 0 COLHDG('Parent Id')
A UID 15P 0 COLHDG('Unique Id')
A CRTDT Z COLHDG('Record created')
A PGMNAM 30A COLHDG('Program Name')
A SVRTY 10 0 COLHDG('Severity')
A TXT 256A COLHDG('Text')
*-------------------------------------------------------------------------
* @Name - JDFHDR
* @Author - Aaron Bartell
* @Desc - Holds JDF header level info.
*-------------------------------------------------------------------------
A UNIQUE
A R JDFHDRR TEXT('JDF Header')
A UID 15P 0 COLHDG('Record Unique Id')
A CRTDT Z COLHDG('Record Created')
A TREETYP 35A COLHDG('Tree Type')
A TREEDEVID 35A COLHDG('Tree DeviceId')
A TREESRVID 35A COLHDG('Tree ServerId')
A TREEURI 35A COLHDG('Tree uri')
A JOBID 50A COLHDG('Job Id')
A K UID
*-------------------------------------------------------------------------
* @Name - JDFRUNLST
* @Author - Aaron Bartell
* @Desc - Holds JDF RunList information.
*-------------------------------------------------------------------------
A UNIQUE
A R JDFRUNLSTR TEXT('JDF RunList')
A PID 15P 0 COLHDG('Parent Unique Id')
A UID 15P 0 COLHDG('Record Unique Id')
A CRTDT Z COLHDG('Record Created')
A RUN 30A COLHDG('Run')
A PGLSTIDX 30A COLHDG('PageListIndex')
A IGNPDLCPY 30A COLHDG('IgnorePDLCopies')
A CMPSN 30A COLHDG('Compression')
A K PID
A K UID
Program: IMPJDF
//------------------------------------------------------------------------
// @Author: Aaron Bartell
// @Created: 2008-02-20
// @Desc: Process JDF (http://xml.coverpages.org/jdf.html) files in an
// IFS directory and parse them into DB2 tables. This program is
// meant to give example to the different coding necessary to
// accomplish the task at hand and not to do a full parsing of the
// XML document.
//------------------------------------------------------------------------
h bnddir('RXSBND': 'QC2LE') dftactgrp(*no)
FJDFCFG if a e k disk prefix('CFG.') usropn
FJDFLOG if a e k disk prefix('LOG.')
FJDFHDR if a e k disk prefix('H.')
FJDFRUNLST if a e k disk prefix('RL.')
d CFG e ds qualified extname(JDFCFG)
d LOG e ds qualified extname(JDFLOG)
d H e ds qualified extname(JDFHDR)
d RL e ds qualified extname(JDFRUNLST)
d EntryParms pr extpgm('IMPJDF')
d EntryParms pi
/copy rxs,RXSCP
d IFSHandler pr
d pFile like(RXS_filePath) value
d pPath like(RXS_filePath) value
d parseHandler pr
d pType value like(RXS_Type)
d pXPath value like(RXS_XPath)
d pData value like(RXS_XmlData)
d pDataLen value like(RXS_Length)
d readJDFCFG pr
d pErr likeds(RXS_Error)
d readIFSDir pr
d pErr likeds(RXS_Error)
d pPath value like(RXS_filePath)
d pProcPtr * value procptr
d debug pr
d pSvrty like(LOG.SVRTY) const
d pTxt like(LOG.TXT) const
d errno pr 10I 0
d errHandler pr
d pCurLine 10i 0 value
d pCurCol 10i 0 value
d pErrStr 1024a value varying
d move pr 10i 0 extproc('Qp0lRenameUnlink')
d from * value Options(*string)
d to * value Options(*string)
d gErr ds likeds(RXS_Error) inz
d gUId s 15 0
d gEnv s 128a varying
/free
monitor;
// Get a unique number to use as a key for physical files.
gUId = RXS_nextUnqNbr();
debug(0: 'Beginning of IMPJDF');
readJDFCFG(gErr);
if CFG.XMLDIR = *blanks or CFG.ACHDIR = *blanks;
debug(100: 'Config file is not setup. All columns must have values.');
return;
endif;
// Invoke the reading of the IFS directories and have all entries found
// in this directory routed to local sub procedure IFSHandler.
readIFSDir(gErr: CFG.XMLDIR: %paddr(IFSHandler));
if gErr.code <> *blanks;
debug(100: gErr.text);
endif;
debug(0: 'End of IMPJDF');
on-error;
gErr = RXS_catchError();
debug(100: gErr.code + gErr.text);
endmon;
*inlr = *on;
/end-free
//------------------------------------------------------------------------
// @Author: Aaron Bartell
// @Created: 2008-02-20
// @Desc: IFSHandler is used to process one IFS file at a time as they are
// found and then move them to an archive directory.
//------------------------------------------------------------------------
p IFSHandler b
d IFSHandler pi
d pFile like(RXS_filePath) value
d pPath like(RXS_filePath) value
d fromIFSFile s like(RXS_filePath)
d toIFSFile s like(RXS_filePath)
/free
fromIFSFile = %trim(pPath) + pFile;
toIFSFile = %trim(CFG.ACHDIR) + pFile;
debug(0:
'fromIFSFile=' + %trim(fromIFSFile) +
' toIFSFile=' + %trim(toIFSFile));
gEnv = '/JobRecord/Tree/JDF/ResourcePool/RunList/RunList';
// parse XML file
RXS_addHandler('/JobRecord>': %paddr(parseHandler));
RXS_addHandler('/JobRecord/>': %paddr(parseHandler));
RXS_addHandler(gEnv + '>': %paddr(parseHandler));
RXS_addHandler(gEnv + '/>': %paddr(parseHandler));
RXS_allAttrHandler(%paddr(parseHandler));
RXS_parse(fromIFSFile: RXS_STMF: %paddr(errHandler));
// Move file to archive directory.
move(%trim(fromIFSFile) : %trim(toIFSFile));
/end-free
p e
//--------------------------------------------------------------------------------------------
// @Author: Aaron Bartell
// @Created: 2008-02-20
// @Desc: Accept parser event notifications and process accordingly.
//--------------------------------------------------------------------------------------------
P parseHandler b
D parseHandler pi
D pType value like(RXS_Type)
D pXPath value like(RXS_XPath)
D pData value like(RXS_XmlData)
D pDataLen value like(RXS_Length)
/free
select;
when pXPath = '/JobRecord>';
clear JDFHDRR;
H.UID = gUId;
H.CRTDT = %timestamp();
when pXPath = '/JobRecord/Tree@type';
H.TREETYP = pData;
when pXPath = '/JobRecord/Tree@deviceId';
H.TREEDEVID = pData;
when pXPath = '/JobRecord/Tree@serverId';
H.TREESRVID = pData;
when pXPath = '/JobRecord/Tree@uri';
H.TREEURI = pData;
when pXPath = '/JobRecord/Tree/JDF@JobID';
H.JOBID = pData;
when pXPath = gEnv +'>';
clear JDFRUNLSTR;
RL.PID = H.UID;
RL.UID = RXS_nextUnqNbr();
RL.CRTDT = %timestamp();
when pXPath = gEnv +'@Run';
RL.RUN = pData;
when pXPath = gEnv +'@PageListIndex';
RL.PGLSTIDX = pData;
when pXPath = gEnv +'/LayoutElement@IgnorePDLCopies';
RL.IGNPDLCPY = pData;
when pXPath = gEnv +'/LayoutElement/FileSpec@Compression';
RL.CMPSN = pData;
when pXPath = gEnv +'/>';
write JDFRUNLSTR;
when pXPath = '/JobRecord/>';
write JDFHDRR;
endsl;
/end-free
P e
//------------------------------------------------------------------------
// @Author: Aaron Bartell
// @Created: 2008-02-20
// @Desc: Write to JDFLOG PF if debug is turned on or if the severity is
// 100.
//------------------------------------------------------------------------
p debug b export
d debug pi
d pSvrty like(LOG.SVRTY) const
d pTxt like(LOG.TXT) const
/free
readJDFCFG(gErr);
if gErr.code <> *blanks;
return;
endif;
// Write a log record only if debugging is turned on or if this is a high
// severity error.
if CFG.DEBUG = 'T' or pSvrty = 100;
clear JDFLOGR;
LOG.PID = gUId; // Parent Id
LOG.UID = RXS_nextUnqNbr();
LOG.CRTDT = %timestamp();
LOG.PGMNAM = 'IMPJDF';
LOG.SVRTY = pSvrty;
LOG.TXT = pTxt;
write JDFLOGR;
endif;
/end-free
p e
//------------------------------------------------------------------------
// @Author: Aaron Bartell
// @Created: 2008-02-20
// @Desc: Read the config file once into this programs memory.
//------------------------------------------------------------------------
p readJDFCFG b
d readJDFCFG pi
d pErr likeds(RXS_Error)
/free
clear pErr;
if %open(JDFCFG);
close JDFCFG;
endif;
open JDFCFG;
read JDFCFG;
if %eof(JDFCFG);
pErr.code = 'JDFO007';
pErr.severity = 100;
pErr.pgm = 'IMPJDF';
pErr.text = 'JDFCFG record not found.';
endif;
/end-free
p e
//------------------------------------------------------------------------
// @Author: Aaron Bartell
// @Created: 2008-02-20
// @Desc: Read through all entries in the IFS directory and process all
// files.
//------------------------------------------------------------------------
p readIFSDir b
d readIFSDir pi
d pErr likeds(RXS_Error)
d pPath value like(RXS_filePath)
d pProcPtr * value procptr
D lstat PR 10I 0 extproc('lstat')
D PathName * value options(*string)
D Buffer likeds(fileInfo)
D opendir PR * extproc('opendir')
D dirname * value options(*string)
D readdir PR * extproc('readdir')
D dirp * value options(*string)
D handleFile pr extproc(pProcPtr)
D pFile like(RXS_filePath) value
D pPath like(RXS_filePath) value
D strerror PR * extproc('strerror')
D errnum 10I 0 value
D dirent ds based(p_dirent)
D d_reserv1 16A
D d_reserv2 10U 0
D d_fileno 10U 0
D d_reclen 10U 0
D d_reserv3 10I 0
D d_reserv4 8A
D d_nlsinfo 12A
D nls_ccsid 10I 0 overlay(d_nlsinfo:1)
D nls_cntry 2A overlay(d_nlsinfo:5)
D nls_lang 3A overlay(d_nlsinfo:7)
D nls_reserv 3A overlay(d_nlsinfo:10)
D d_namelen 10U 0
D d_name 640A
D fileInfo DS qualified
D align
D st_mode 5U 0
D st_ino 10U 0
D st_nlink 5U 0
D st_uid 10U 0
D st_gid 10U 0
D st_size 10I 0
D st_atime 10I 0
D st_mtime 10I 0
D st_ctime 10I 0
D st_dev 10U 0
D st_blksize 10U 0
D st_allocsize 10U 0
D st_objtype 11A
D st_codepage 5U 0
D st_ccsid 5U 0
D st_reserved 60A
D st_ino_gen_id 10U 0
// a few local variables...
D dh S *
D p_dirent s *
D name S 256a varying
D success S 10I 0
/FREE
// Open up the directory.
dh = opendir(%trim(pPath));
if dh = *NULL;
pErr.code = 'MKTLIVE999';
pErr.text =
'opendir error: '+ %trim(%str(strerror(errno))) + ' Path:' + pPath;
return;
endif;
// Read each entry from the directory (in a loop)
p_dirent = readdir(dh);
dow p_dirent <> *NULL;
name = %str(%addr(d_name));
// Call lstat so we can check to see if this is a stream file
success = lstat(%trim(pPath) + %trim(name): fileinfo);
if success >= 0 and %trim(fileInfo.st_objtype: x'00') = '*STMF';
//Make a "call back" to the procedure pointer.
handleFile(name: pPath);
endif;
p_dirent = readdir(dh);
enddo;
return;
/end-free
p e
//-------------------------------------------------------------------
// Retrieve the error number for UNIX-type APIs
//-------------------------------------------------------------------
P errno B
D errno PI 10I 0
D @__errno PR * extproc('__errno')
D p_errno S *
D wwreturn S 10I 0 based(p_errno)
/FREE
p_errno = @__errno;
return wwreturn;
/END-FREE
P E
//--------------------------------------------------------------------------------------------
// @Author: Aaron Bartell
// @Created: 2008-02-20
// @Desc:
//--------------------------------------------------------------------------------------------
P errHandler B
D errHandler PI
D pCurLine 10i 0 value
D pCurCol 10i 0 value
D pErrStr 1024a value varying
/free
gErr.code = 'IMPJDF001';
gErr.severity = 100;
gErr.pgm = 'IMPJDF.errHandler';
gErr.text =
'Line:' + %char(pCurLine) +' Col:' + %char(pCurCol) +' ' + pErrStr;
/end-free
P E
Example file being parsed:
<JobRecord>
<Tree type="Oai.Gep.Jdf.Job, Oai.Gep" deviceId="dev01" serverId="server2" uri="file:///c:/data/jdfJobs/Trans_ea18d701-9ad8-4564-b47e-4fa32dcf334b/ctl080201-mag.jdf" lastUpdatedDateTime="2/1/2008 11:39:32 AM">
<JDF xmlns:oai="http://www.oai.cc/JDFExtension_1_3" xmlns="http://www.CIP4.org/JDFSchema_1_1" JobID="ctl080201-mag" oai:PrintOrder="00000290" ID="CTL080201-MAG" Status="Waiting" JobPartID="000" DescriptiveName="1006 Control Engineering" oai:IssueDate="2008-02-01" oai:PageLogJobId="39062" oai:PrinergyJobId="290_3487_CTL_FEB08" Version="1.3" oai:JobId="00000290_003487_39062" ProjectID="003487" Type="Product" Template="false">
<ResourcePool>
<BindingIntent BindingOrder="Gathering" Class="Intent" ID="BindingIntent_CTL080201-MAG" Locked="false" PartUsage="Explicit" SpawnStatus="NotSpawned" Status="Available">
<BindingType DataType="EnumerationSpan" Actual="SoftCover" />
</BindingIntent>
<RunList ComponentGranularity="Document" DocCopies="1" IsPage="true" PageCopies="1" SetCopies="1" Class="Parameter" NoOp="false" ID="RunList_Body_CTL080201-MAG" Locked="false" PartUsage="Explicit" SpawnStatus="NotSpawned" Status="Unavailable" DescriptiveName="Text Pages" PartIDKeys="Run Edition" NPage="100" Directory="D:\GBExpress_in\RbiPdf">
<RunList Run="0" PageListIndex="0" Status="Available">
<LayoutElement IgnorePDLCopies="false" IgnorePDLImposition="true">
<FileSpec Compression="None" URL="ctl080201-MAG_0001.pdf" />
</LayoutElement>
</RunList>
<PageListRef rRef="PageList_CTL080201-MAG" />
<RunList Run="1" PageListIndex="1" Status="Available">
<LayoutElement IgnorePDLCopies="false" IgnorePDLImposition="true">
<FileSpec Compression="None" URL="ctl080201-MAG_0002.pdf" />
</LayoutElement>
</RunList>
<RunList Run="2" PageListIndex="2" Status="Available">
<LayoutElement IgnorePDLCopies="false" IgnorePDLImposition="true">
<FileSpec Compression="None" URL="ctl080201-MAG_0003.pdf" />
</LayoutElement>
</RunList>
<RunList Run="3" PageListIndex="3" Status="Available">
<LayoutElement IgnorePDLCopies="false" IgnorePDLImposition="true">
<FileSpec Compression="None" URL="ctl080201-MAG_0004.pdf" />
</LayoutElement>
</RunList>
<RunList Run="4" PageListIndex="4" Status="Available">
<LayoutElement IgnorePDLCopies="false" IgnorePDLImposition="true">
<FileSpec Compression="None" URL="ctl080201-MAG_0005.pdf" />
</LayoutElement>
</RunList>
<RunList Run="5" PageListIndex="5" Status="Available">
<LayoutElement IgnorePDLCopies="false" IgnorePDLImposition="true">
<FileSpec Compression="None" URL="ctl080201-MAG_0006.pdf" />
</LayoutElement>
</RunList>
<RunList Run="6" PageListIndex="6" Status="Available">
<LayoutElement IgnorePDLCopies="false" IgnorePDLImposition="true">
<FileSpec Compression="None" URL="ctl080201-MAG_0007.pdf" />
</LayoutElement>
</RunList>
<RunList Run="7" PageListIndex="7" Status="Available">
<LayoutElement IgnorePDLCopies="false" IgnorePDLImposition="true">
<FileSpec Compression="None" URL="ctl080201-MAG_0008.pdf" />
</LayoutElement>
</RunList>
<RunList Run="8" PageListIndex="8" Status="Available">
<LayoutElement IgnorePDLCopies="false" IgnorePDLImposition="true">
<FileSpec Compression="None" URL="ctl080201-MAG_0009.pdf" />
</LayoutElement>
</RunList>
<RunList Run="9" PageListIndex="9" Status="Available">
<LayoutElement IgnorePDLCopies="false" IgnorePDLImposition="true">
<FileSpec Compression="None" URL="ctl080201-MAG_0010.pdf" />
</LayoutElement>
</RunList>
<RunList Run="10" PageListIndex="10" Status="Available">
<LayoutElement IgnorePDLCopies="false" IgnorePDLImposition="true">
<FileSpec Compression="None" URL="ctl080201-MAG_0011.pdf" />
</LayoutElement>
</RunList>
<RunList Run="11" PageListIndex="11" Status="Available">
<LayoutElement IgnorePDLCopies="false" IgnorePDLImposition="true">
<FileSpec Compression="None" URL="ctl080201-MAG_0012.pdf" />
</LayoutElement>
</RunList>
<RunList Run="12" PageListIndex="12" Status="Available">
<LayoutElement IgnorePDLCopies="false" IgnorePDLImposition="true">
<FileSpec Compression="None" URL="ctl080201-MAG_0013.pdf" />
</LayoutElement>
</RunList>
<RunList Run="13" PageListIndex="13" Status="Available">
<LayoutElement IgnorePDLCopies="false" IgnorePDLImposition="true">
<FileSpec Compression="None" URL="ctl080201-MAG_0014.pdf" />
</LayoutElement>
</RunList>
<RunList Run="14" PageListIndex="14" Status="Available">
<LayoutElement IgnorePDLCopies="false" IgnorePDLImposition="true">
<FileSpec Compression="None" URL="ctl080201-MAG_0015.pdf" />
</LayoutElement>
</RunList>
<RunList Run="15" PageListIndex="15" Status="Available">
<LayoutElement IgnorePDLCopies="false" IgnorePDLImposition="true">
<FileSpec Compression="None" URL="ctl080201-MAG_0016.pdf" />
</LayoutElement>
</RunList>
<RunList Run="16" PageListIndex="16" Status="Available">
<LayoutElement IgnorePDLCopies="false" IgnorePDLImposition="true">
<FileSpec Compression="None" URL="ctl080201-MAG_0017.pdf" />
</LayoutElement>
</RunList>
<RunList Run="17" PageListIndex="17" Status="Available">
<LayoutElement IgnorePDLCopies="false" IgnorePDLImposition="true">
<FileSpec Compression="None" URL="ctl080201-MAG_0018.pdf" />
</LayoutElement>
</RunList>
<RunList Run="18" PageListIndex="18" Status="Available">
<LayoutElement IgnorePDLCopies="false" IgnorePDLImposition="true">
<FileSpec Compression="None" URL="ctl080201-MAG_0019.pdf" />
</LayoutElement>
</RunList>
<RunList Run="19" PageListIndex="19" Status="Available">
<LayoutElement IgnorePDLCopies="false" IgnorePDLImposition="true">
<FileSpec Compression="None" URL="ctl080201-MAG_0020.pdf" />
</LayoutElement>
</RunList>
<RunList Run="20" PageListIndex="20" Status="Available">
<LayoutElement IgnorePDLCopies="false" IgnorePDLImposition="true">
<FileSpec Compression="None" URL="ctl080201-MAG_0021.pdf" />
</LayoutElement>
</RunList>
</RunList>
<PageList Template="false" Class="Parameter" NoOp="false" ID="PageList_CTL080201-MAG" Locked="false" PartUsage="Explicit" SpawnStatus="NotSpawned" Status="Available">
<ContentList>
<ContentData ContentType="Ad" />
<ContentData ContentType="Editorial" />
</ContentList>
<PageData PageLabel="1" DescriptiveName="OMEGA ENGINEERING INC/">
<PageElement ContentListIndex="0" />
<SeparationSpec Name="Cyan" />
<SeparationSpec Name="Magenta" />
<SeparationSpec Name="Yellow" />
<SeparationSpec Name="Black" />
</PageData>
<PageData PageLabel="2" DescriptiveName="/Marcs Editorial w/mast">
<PageElement ContentListIndex="1" />
<SeparationSpec Name="Cyan" />
<SeparationSpec Name="Magenta" />
<SeparationSpec Name="Yellow" />
<SeparationSpec Name="Black" />
</PageData>
<PageData PageLabel="3" DescriptiveName="WONDERWARE CORP/">
<PageElement ContentListIndex="0" />
<SeparationSpec Name="Cyan" />
<SeparationSpec Name="Magenta" />
<SeparationSpec Name="Yellow" />
<SeparationSpec Name="Black" />
</PageData>
<PageData PageLabel="4" DescriptiveName="HONEYWELL INC/">