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/">