XML in 6.x

Post questions here relative to DataStage Server Edition for such areas as Server job design, DS Basic, Routines, Job Sequences, etc.

Moderators: chulett, rschirm, roy

Post Reply
rdy
Participant
Posts: 38
Joined: Wed Nov 05, 2003 2:40 pm

XML in 6.x

Post by rdy »

What addons do I need to generate XML files in 6.x?
ogmios
Participant
Posts: 659
Joined: Tue Mar 11, 2003 3:40 pm

Re: XML in 6.x

Post by ogmios »

rdy wrote:What addons do I need to generate XML files in 6.x?
If you write your own XML files via a BASIC job nothing... in the other case the "XML pack", preferably the latest version available at your local DataStage (re)seller.

And remember DataStage cannot read/produce all types of possible XML files (think in terms of converting an XML file to rows and rows to an XML file).

Ogmios
rdy
Participant
Posts: 38
Joined: Wed Nov 05, 2003 2:40 pm

Re: XML in 6.x

Post by rdy »

ogmios wrote: If you write your own XML files via a BASIC job nothing
Have any sample code you can share?
ogmios
Participant
Posts: 659
Joined: Tue Mar 11, 2003 3:40 pm

Re: XML in 6.x

Post by ogmios »

rdy wrote:
ogmios wrote: If you write your own XML files via a BASIC job nothing
Have any sample code you can share?
Not directly... but here's the deal:
- When reading input from a database open a cursor on your data.
- Write the XML tags and data in the format you need to a file

If you have only a few XML files to generate this is very much doable.

Ogmios
kduke
Charter Member
Charter Member
Posts: 5227
Joined: Thu May 29, 2003 9:47 am
Location: Dallas, TX
Contact:

Post by kduke »

Ray posted some code where he dumped DS_METADATA file into XML. It was all written in BASIC. Very clean easy to read. Do a search.
Mamu Kim
rdy
Participant
Posts: 38
Joined: Wed Nov 05, 2003 2:40 pm

Ray's code

Post by rdy »

kduke wrote:Ray posted some code where he dumped DS_METADATA file into XML. It was all written in BASIC. Very clean easy to read. Do a search.
I searched for it and found a link to that topic, but the link was dead. Anyone have a hint how I can track it down?
kduke
Charter Member
Charter Member
Posts: 5227
Joined: Thu May 29, 2003 9:47 am
Location: Dallas, TX
Contact:

Post by kduke »

Sorry, you are correct. It is not available to the forum.
Mamu Kim
Baldmartyr
Participant
Posts: 108
Joined: Mon Oct 21, 2002 8:30 am

Post by Baldmartyr »

Please post the URL for the dead link so that I can see what the issue is.
David Baldwin
Former DSXchange Webmaster
ray.wurlod
Participant
Posts: 54607
Joined: Wed Oct 23, 2002 10:52 pm
Location: Sydney, Australia
Contact:

Post by ray.wurlod »

It was posted in Inner Circle, as a tool suitable for self-employed consultants to gain leverage when bidding for work.
Correctly it is not visible to non-members of the Inner Circle.
IBM Software Services Group
Any contribution to this forum is my own opinion and does not necessarily reflect any position that IBM may hold.
kduke
Charter Member
Charter Member
Posts: 5227
Joined: Thu May 29, 2003 9:47 am
Location: Dallas, TX
Contact:

Post by kduke »

Sorry, Ray. My bad. Anyway it is very cool.
Mamu Kim
ray.wurlod
Participant
Posts: 54607
Joined: Wed Oct 23, 2002 10:52 pm
Location: Sydney, Australia
Contact:

Post by ray.wurlod »

Here's a sanitized version. Apologies for the paucity of comments.

Code: Select all

FUNCTION DumpTableDefinitions(TableDefinition, OutputFormat, ProjectName, ProjectDescription, OutputFile, Delimiter, OpenMode, HeaderLine, IncludeNullable, IncludeDescription)

$COPYRIGHT "Copyright (c) 2002, Ray Wurlod.  All rights reserved.  May be reproduced with this copyright notice intact." 

* 
* History 
* ======= 
*   Date    Who               Version  Details of Modification 
* --------  ----------------  -------  ----------------------------------- 
* 27/09/04  Ray Wurlod         20.0.3  Sanitized version for DSXChange
* 20/11/02  Ray Wurlod         20.0.2  Remove previous trailer when OpenMode is "Append" and file exists. 
* 10/09/02  Ray Wurlod         20.0.0  Initial Coding. 
* 

* 
* Notice 
* ====== 
* The algorithm used in this code depends on knowledge that is proprietary to Ascential Software, Inc. 
* No guarantee is either expressly given or implied that the code will continue to function beyond the 
* release of DataStage current when it was written (release 5.2). 
* 


* 
* Design 
* ====== 
*  1.  Determine that table definition name supplied is unique in Repository, else generate warning message and stop. 
*  2.  Open the output file for writing, else generate warning and stop. 
*  3.  Read the table definition record from DS_METADATA. 
*  4.  Generate required output, write to file, and log success message. 
* 

* Add in header file in which SQL data types are enumerated. 
$INCLUDE DSINCLUDE DSD_BCI.H 
* Add in header file in which DataStage common constants are declared. 
$INCLUDE DSINCLUDE DSR_COMCONST.H 
* Add in header file with constants for SelectInfo function. 
$INCLUDE UNIVERSE.INCLUDE INFO_KEYS.H 
* Set indent size for XML output 
$DEFINE XMLINDENTSIZE 3 

* Pre-evaluate functions at compile time 
      Equate CR To Char(10) ; Equate XMLCR To "
" 
      Equate LF To Char(13) ; Equate XMLLF To "
" 
      Equate XMLQuote To """ 

* Determine machine name of server, O/S-specific command names 
      If System(91) 
      Then 
         Shell = "DOS" 
         DeleteFileCommand = "DEL " 
         CopyFileCommand = "COPY " 
      End 
      Else 
         Shell = "SH" 
         DeleteFileCommand = "rm " 
         CopyFileCommand = "cp " 
      End 
      Call DSExecute(Shell, "hostname", lServerName, Code) 
      lServerName = (If Code = 0 Then lServerName<1> Else "unknown") 


* Read argument values into local variable to avoid side-effects if they're changed
      pTableDefinition = TableDefinition
      If IsNull(pTableDefinition) Or Trim(pTableDefinition) = "" 
      Then 
         Message = "No table definition or category name." 
         Call DSLogWarn(Message, "DumpColumnDefinitions") 
         GoTo MainExit 
      End 
      pOutputFormat = OutputFormat
      pProjectName = ProjectName
      pProjectDescription = ProjectDescription
      pOutputFile = OutputFile
      If System(91) Then Convert "/" To "\" In pOutputFile 
      pDelimiter = Delimiter
      pOpenMode = OpenMode
      pHeaderLine = HeaderLine
      pIncludeNullable = IncludeNullable
      pIncludeDescription = IncludeDescription

* In steps 1 and 2, a non-empty value in this variable will cause an abnormal exit. 
      Message = "" 


*  1.  Determine that table definition name supplied is unique in Repository, else generate warning message and stop. 
*      Another possibility is that the TableDefinition parameter contains the name of a Category, in which case verify 
*      that this name exists in the DS_METADATA table. 

      Open "DS_METADATA" to fDSMETADATA 
      On Error 
         Message = "Unable to open Table Definitions table DS_METADATA in Repository." 
         Message<-1> = "  System error code = " : Status() : "." 
      End 
      Then 

         * Select List number 10 will be used for list of table definition names 
         ClearSelect 10 

         Command = "SELECT DS_METADATA WITH DSRID LIKE " : Quote("0X'" : pTableDefinition : "'0X") : " TO 10" 
         Call DSExecute("UV", Command, Output, Code) 

         If Selectinfo(10, IK$SLACTIVE) <= 0 
         Then 
            Message = "Unable to find " : Quote(pTableDefinition) : " in DataStage Repository." 
         End 
         Else 

            nTableCount = SelectInfo(10, IK$SLCOUNT) 
            If nTableCount > 1 
            Then 
               * Name entered was Category name. 
               * Select List number 10 contains more than one entry. 
               !!!! Code removed in version 20.0.1 
               ! Message = "More than one Table Definition found based on name " : Quote(pTableDefinition) 
               ! ReadList lTableDefinitions From 10 Else TableDefinitions = "" 
               ! Message<-1> = lTableDefinitions 
               !!!! End of removed code 
            End 
            Else 
               * Name entered was Table Definition name. 
               * Select List number 10 contains 1 entry. 
               !!!! Code removed in version 20.0.1 
               ! ReadList lTableDefinition From 10 Else lTableDefinition = "" 
               ! kDSMETADATA = lTableDefinition 
               !!!! End of removed code 
            End                          ; * end of test for more than one Table Definition 

         End                             ; * end of test for empty Select List 

      End 
      Else 
         Message = "Unable to open Table Definitions table DS_METADATA in Repository." 
         Message<-1> = "  System error code = " : Status() : "." 
      End 

      If Len(Message) 
      Then 
         Call DSLogWarn(Message, "Dump Column Definitions") 
         Return                          ; * abnormal exit 
      End 


*  2.  Open the output file for writing, else generate warning and stop. 

      !!! Code added in version 20.0.2 
      If pOpenMode = "Append" 
      Then 
         Begin Case 
            Case pOutputFormat = "Delimited" 
               NULL 
            Case pOutputFormat = "INTEGRITY" 
               GoSub IntegrityEOF        ; * remove "END #DATATABLE" and following lines 
            Case pOutputFormat = "XML" 
               GoSub XMLEOF              ; * remove "</TableDefinition>" and following lines 
               Indent = 2 * XMLINDENTSIZE          ; * initialize indent for next record 
         End Case 
      End 
      !!! End of code added in version 20.0.2 

      OpenSeq pOutputFile To fOutputFile 
      On Error 
         Message = "Unable to open " : Quote(pOutputFile) : " for writing." 
         Message<-1> = "System error code = " : Status() : "." 
      End 
      Locked 
         Message = "Unable to open " : Quote(pOutputFile) : " for writing." 
         Message<-1> = "File locked for update by process number = " : Status() : "." 
      End 
      Then 
         If pOpenMode = "Overwrite" 
         Then 
            WeofSeq fOutputFile          ; * truncate file for overwriting 
            lHeaderRequired = @TRUE 
         End 
         Else 
            * Position to end of file, removing previous trailer if required 
            Seek fOutputFile, 0, 2 Else NULL       ; * position to end of file for appending 
            lHeaderRequired = @FALSE 
         End 
      End 
      Else 
         If Status() = 0 
         Then 
            lHeaderRequired = @TRUE      ; * file opened OK (but doesn't exist yet) 
         End 
         Else 
            Message = "Unable to open " : Quote(pOutputFile) : " for writing." 
            Message<-1> = "System error code = " : Status() : "." 
         End 
      End                                ; * end of OpenSeq statement 

      If Len(Message) 
      Then 
         Call DSLogWarn(Message, "Dump Column Definitions") 
         Return                          ; * abnormal exit 
      End 



*  3.  Read the table definition record(s) from DS_METADATA.  Create header if necessary.  Dump table defintion(s). 
*      Create trailer if necessary. 

      TableDefinitionCount = 0 
      If lHeaderRequired 
      Then 
         Begin Case 
               * Generate table header information into output file 
            Case pOutputFormat = "Delimited" 
               GoSub DelimitedHeader 
            Case pOutputFormat = "INTEGRITY" 
               GoSub IntegrityHeader 
            Case pOutputFormat = "XML" 
               GoSub XMLHeader 
         End Case 
      End 

      Loop 
      While ReadNext kDSMETADATA From 10 

         * Make sure the record is not a Category record, names of which begin with "\\\". 
         If kDSMETADATA[1,3] <> "\\\" 
         Then 

            ReadU rDSMETADATA From fDSMETADATA, kDSMETADATA 
            On Error 
               Message = "Unable to read Table Definition from DS_METADATA in Repository." 
               Message<-1> = "  System error code = " : Status() : "." 
            End 
            Locked 
               Message = "Table Definition record " : Quote(kDSMETADATA) : " locked by other user." 
               Message<-1> = "  DataStage ID of that user = " : Status() : "." 
            End 
            Then 
               pTableDefinition = Field(kDSMETADATA, "\", Count(kDSMETADATA,"\") + 1, 1) 
               lOccurrence = 1 
               GoSub ProcessTableDefinition        ; * record read successfully 
               TableDefinitionCount += 1 
            End 
            Else 
               Message = "Table Definition record " : Quote(kDSMETADATA) : " not found in DS_METADATA table in Repository." 
               Message<-1> = "  System error code = " : Status() : "." 
            End 

            If Len(Message) 
            Then 
               Message<-1> = "  Processing of table definition " : Quote(kDSMETADATA) : " skipped." 
               Call DSLogWarn(Message, "Dump Column Definitions") 
            End 

            Release fDSMETADATA, kDSMETADATA       ; * release exclusive lock on record 

         End                             ; * end of IF test for Category record in DS_METADATA 

      Repeat 

      * Generate table trailer information into output file. 
      Begin Case 
         Case pOutputFormat = "Delimited" 
            NULL                         ; * no trailer required 
         Case pOutputFormat = "INTEGRITY" 
            GoSub IntegrityTrailer 
         Case pOutputFormat = "XML" 
            GoSub XMLTrailer 
      End Case 

      CloseSeq fOutputFile 
      Close fDSMETADATA 

      If TableDefinitionCount = 1 
         Then Message = "One table definition dumped." 
         Else Message = TableDefinitionCount : " table definitions dumped." 
      Call DSLogInfo(Message, "Dump Column Definitions") 

MainExit: 
      Ans = 0
      RETURN(Ans) 



************************************************************ 
ProcessTableDefinition: 
************************************************************ 

*  4.  Generate required output, write to file, and log success message. 

      Message = "" 

      lTableName = Field(kDSMETADATA, "\", Count(kDSMETADATA, "\") + 1, 1) 
      lTableShortDesc = Raise(rDSMETADATA<DSR.DICT.DESC>) 

      FindStr "CMetaColumn" In rDSMETADATA, lOccurrence Setting FMC,VMC,SMC 
      Then 

         nColumns = Field(rDSMETADATA<FMC>, "/", 2, 1)       ; * number of column definitions in collection 
         If nColumns = 0 
         Then 
            * Stored procedures use the second columns collection in the record. 
            * Go get the next one. 
            lOccurrence += 1 
            GoTo ProcessTableDefinition 
         End 

         * Replace double-quotes, carriage return and line feed with appropriate XML tokens 
         If pOutputFormat = "XML" 
         Then 
            rDSMETADATA = Ereplace(rDSMETADATA, '"', XMLQuote, -1, 0) 
            rDSMETADATA = Ereplace(rDSMETADATA, CR, XMLCR, -1, 0) 
            rDSMETADATA = Ereplace(rDSMETADATA, LF, XMLLF, -1, 0) 
         End 

         * Convert multi-valued fields to field-mark-delimited dynamic arrays, so as to take advantage 
         * of hint structure in subsequent processing. 
         lColumnNames = Raise(rDSMETADATA<FMC+1>) 
         lColumnDescriptions = Raise(rDSMETADATA<FMC+2>) 
         lDataElements = Raise(rDSMETADATA<FMC+3>) 
         lSQLDataTypeCodes = Raise(rDSMETADATA<FMC+4>) 
         lPrecision = Raise(rDSMETADATA<FMC+5>) 
         lScale = Raise(rDSMETADATA<FMC+6>) 
         lIsNullable = Raise(rDSMETADATA<FMC+7>) 
         lKeyPosition = Raise(rDSMETADATA<FMC+8>) 
         lDisplayWidth = Raise(rDSMETADATA<FMC+9>) 
         * The final three are for UniVerse and UniData files/tables 
         lAssociation = Raise(rDSMETADATA<FMC+10>) 
         lFieldPos = Raise(rDSMETADATA<FMC+11>) 
         lFieldType = Raise(rDSMETADATA<FMC+12>) 


         * Generate column definitions into output file. 
         WriteCount = 0 
         WriteFailCount = 0 
         Begin Case 
            Case pOutputFormat = "Delimited" 
               GoSub DumpDelimited 
            Case pOutputFormat = "INTEGRITY" 
               GoSub DumpIntegrity 
            Case pOutputFormat = "XML" 
               GoSub DumpXML 
         End Case 
         MsgText = "Found " : nColumns : " column definition" : (If nColumns = 1 Then "" Else "s") 
         MsgText := " for table definition " : Quote(pTableDefinition) : "." 
         MsgText<-1> = Lines 
         MsgText<-1> = "  Wrote " : WriteCount : " column definitions to " : Quote(pOutputFile) : "." 
!!       MsgText<-1> = "  Failed to write " : WriteFailCount : "." 
         Call DSLogInfo(MsgText, "Dump Column Definitions") 

      End 
      Else 
         Message = "Could not find CMetaColumn collection in DS_METADATA record " : Quote(kDSMETADATA) : "." 
      End                                ; * end of FindStr statement 

      If Len(Message) 
      Then 
         Call DSLogWarn(Message, "Dump Column Definitions") 
      End 

      Return(0)                             ; * end of ProcessTableDefinition internal subroutine 


************************************************************ 
DumpDelimited: 
************************************************************ 


      Lines = "" 

      lTableQualifier = (If nTableCount = 1 Then "" Else pTableDefinition : ".") 

      For k = 1 To nColumns 
         Line = DQuote(lTableQualifier : lColumnNames<k>) : cDelimiter 
         SQLDataType = DQuote(Field(SQL.TYPE.NAMES, ",", lSQLDataTypeCodes<k>, 1)) 
         Line := SQLDataType : cDelimiter 
         Line := lPrecision<k> : cDelimiter 
         If SQLDataType = "Decimal" Or SQLDataType = "Numeric" 
         Then 
            Line := lScale<k> 
         End 
         Line := cDelimiter 
         If pIncludeNullable = "Yes" 
         Then 
            Line := (If lIsNullable<k> Then "Y" Else "N") : cDelimiter 
         End 
         Line := (If lKeyPosition<k> Then "Y" Else "N") 
         If pIncludeDescription = "Yes" 
         Then 
            Line := cDelimiter : DQuote(lColumnDescriptions<k>) 
         End 
         WriteSeq Line To fOutputFile 
         Then 
            WriteCount += 1 
            Lines<-1> = "    " : Line 
         End 
         Else 
            WriteFailCount += 1 
         End 
      Next k 

      Return(0)                             ; * end of DumpDelimited internal subroutine 



************************************************************ 
DumpIntegrity: 
************************************************************ 


      ColStart = 1 
      pMaxRecordLength = 0 

      For k = 1 To nColumns 
         If lDisplayWidth<k> = 0 
         Then 
            pMaxRecordLength += lPrecision<k> + lScale<k> 
         End 
         Else 
            pMaxRecordLength += lDisplayWidth<k> 
         End 
      Next k 

      If (IsNull(lTableShortDesc[1,40]) OR Trim(lTableShortDesc) = "") 
      Then 
         lTableShortDesc = "No Table Desc" 
      End 

      WriteSeq " " To fOutputFile Else NULL 
      WriteSeq "    DATAFILE BEGIN" To fOutputFile Else NULL 
      WriteSeq "      NAME                       ":pTableDefinition[1,8] To fOutputFile Else NULL 
      WriteSeq "      DESCRIPTION                ":lTableShortDesc[1,40] To fOutputFile Else NULL 
      WriteSeq "      MAXRECORDLENGTH            ":pMaxRecordLength To fOutputFile Else NULL 
      WriteSeq "      FORMAT                     FIXEDTERM" To fOutputFile Else NULL 
      WriteSeq "      CODEPAGE                   NATIVE" To fOutputFile Else NULL 
      WriteSeq " " To fOutputFile Else NULL 

      For k = 1 To nColumns 

         If (IsNull(lColumnDescriptions<k>) OR Trim(lColumnDescriptions<k>) = "") 
         Then 
            lColumnDescriptions<k> = "No Col Desc" 
         End 

         If lDisplayWidth<k> = 0 
         Then 
            lDisplayWidth<k> = lPrecision<k> + lScale<k> 
         End 

         If (lSQLDataTypeCodes<k> = "2" OR lSQLDataTypeCodes<k> = "3" OR lSQLDataTypeCodes<k> = "4" OR lSQLDataTypeCodes<k> = "5" OR lSQLDataTypeCodes<k> = "6" OR lSQLDataTypeCodes<k> = "7" OR lSQLDataTypeCodes<k> = "8" OR lSQLDataTypeCodes<k> = "17" OR lSQLDataTypeCodes<k> = "19") 
         Then 
            pSQLIntType = "I"            ; * I for Integer (DataStage - Numeric, Decimal,Integer,SmallInt,Float,Real,Double,BigInt,TinyInt) 
         End 
         Else 
            pSQLIntType = "S"            ; * S for String  (DataStage - Char,Date,Time,Timestamp,VarChar,LongVarChar,Binary,VarBinary,LongVarBinary,Bit" 

         End 

         WriteSeq "      FIELD BEGIN" To fOutputFile Else NULL 
         WriteSeq "        NAME                     ":lColumnNames<k>[1,7] To fOutputFile Else NULL 
         WriteSeq "        DESCRIPTION              ":Field((lColumnDescriptions<k>[1,40]),LF,"1") To fOutputFile Else NULL 
         WriteSeq "        STARTPOSITION            ":ColStart To fOutputFile Else NULL 
         WriteSeq "        LENGTH                   ":lDisplayWidth<k> To fOutputFile Else NULL 
         WriteSeq "        DATATYPE                 ALPHANUM" To fOutputFile Else NULL 
         WriteSeq "        USETYPE                  ":pSQLIntType To fOutputFile Else NULL 
         WriteSeq "        MISSINGVALUE             S" To fOutputFile Else NULL 
         WriteSeq "      END" To fOutputFile Then WriteCount += 1 Else WriteFailCount += 1 
         WriteSeq " " To fOutputFile Else NULL 

         ColStart += lDisplayWidth<k> 

      Next k 

      WriteSeq "    END" To fOutputFile Else NULL 

      Return(0)                             ; * end of DumpIntegrity internal subroutine 



************************************************************ 
DumpXML: 
************************************************************ 

      * Date/time modified is recorded in the DS_AUDIT file.  We get it from there 
      * using the Trans() function (lazy programming). 
      AuditInfo = Raise(Trans("DS_AUDIT", "4\" : kDSMETADATA, -1, "X")) 
      DTC = AuditInfo<1> 
      DTM = AuditInfo<5,1> 
      If DTM = "" 
      Then 
         DateModified = DTC[1,10] 
         TimeModified = DTC[12,8] 
      End 
      Else 
         DateModified = DTM[1,10] 
         TimeModified = DTM[12,8] 
      End 
      Convert ":" To "." In TimeModified 

      CurrentIndent = Space(Indent) 
      Line = CurrentIndent : "<Record Identifier=" : DQuote(kDSMETADATA) 
      Line := " DateModified=" : DQuote(DateModified) 
      Line := " TimeModified=" : DQuote(TimeModified) 
      Line := ' Type="MetaTable"' 
      Line := " Readonly=" : DQuote(rDSMETADATA<1> <> "NRO") : ">" 
      WriteSeq Line To fOutputFile Else NULL 

      Indent += XMLINDENTSIZE 
      CurrentIndent = Space(Indent) 

      Line = CurrentIndent : '<Property Name="ShortDesc">' : rDSMETADATA<4> : '</Property>' 
      WriteSeq Line To fOutputFile Else NULL 

      If IsNull(rDSMETADATA<5>) Or Trim(rDSMETADATA<5>) = "" 
      Then 
         rDSMETADATA<5> = "(none)" 
      End 
      Line = CurrentIndent : '<Property Name="Description" PreFormatted="1">' : rDSMETADATA<5> : '</Property>' 
      WriteSeq Line To fOutputFile Else NULL 

      Line = CurrentIndent : '<Property Name="Version">' : rDSMETADATA<6> : '</Property>' 
      WriteSeq Line To fOutputFile Else NULL 

      Line = CurrentIndent : '<Property Name="QuoteChar">' : rDSMETADATA<8> : '</Property>' 
      WriteSeq Line To fOutputFile Else NULL 

      Line = CurrentIndent : '<Property Name="Multivalued">' : rDSMETADATA<9> : '</Property>' 
      WriteSeq Line To fOutputFile Else NULL 

      Line = CurrentIndent : '<Property Name="SPErrorCodes">' : rDSMETADATA<10> : '</Property>' 
      WriteSeq Line To fOutputFile Else NULL 

      Line = CurrentIndent : '<Collection Name="Columns" Type="MetaColumn">' 
      WriteSeq Line To fOutputFile Else NULL 

      Indent += XMLINDENTSIZE 
      CurrentIndent = Space(Indent) 

      For k = 1 To nColumns 

         Line = CurrentIndent : '<SubRecord>' 
         WriteSeq Line To fOutputFile Else NULL 

         Indent += XMLINDENTSIZE 
         CurrentIndent = Space(Indent) 

         Line = CurrentIndent : '<Property Name="Name">' : lColumnNames<k> : '</Property>' 
         WriteSeq Line To fOutputFile Else NULL 
         If IsNull(lColumnDescriptions<k>) Or Trim(lColumnDescriptions<k>) = "" 
         Then 
            lColumnDescriptions<k> = "(none)" 
         End 
         Line = CurrentIndent : '<Property Name="Description" Preformatted="1">' : lColumnDescriptions<k> : '</Property>' 
         WriteSeq Line To fOutputFile Else NULL 
         Line = CurrentIndent : '<Property Name="SQLType">' : lSQLDataTypeCodes<k> : '</Property>' 
         WriteSeq Line To fOutputFile Else NULL 
         Line = CurrentIndent : '<Property Name="Precision">' : lPrecision<k> : '</Property>' 
         WriteSeq Line To fOutputFile Else NULL 
         Line = CurrentIndent : '<Property Name="Scale">' : lScale<k> : '</Property>' 
         WriteSeq Line To fOutputFile Else NULL 
         Line = CurrentIndent : '<Property Name="Nullable">' : lIsNullable<k> : '</Property>' 
         WriteSeq Line To fOutputFile Else NULL 
         Line = CurrentIndent : '<Property Name="KeyPosition">' : lKeyPosition<k> : '</Property>' 
         WriteSeq Line To fOutputFile Else NULL 
         Line = CurrentIndent : '<Property Name="DisplaySize">' : lDisplayWidth<k> : '</Property>' 
         WriteSeq Line To fOutputFile Else NULL 
         Line = CurrentIndent : '<Property Name="Association">' : lAssociation<k> : '</Property>' 
         WriteSeq Line To fOutputFile Else NULL 
         Line = CurrentIndent : '<Property Name="FieldPos">' : lFieldPos<k> : '</Property>' 
         WriteSeq Line To fOutputFile Else NULL 
         Line = CurrentIndent : '<Property Name="FieldType">' : lFieldType<k> : '</Property>' 
         WriteSeq Line To fOutputFile Else NULL 
         Line = CurrentIndent : '<Property Name="PadChar"/> 
         WriteSeq Line To fOutputFile Else NULL 

         Indent -= XMLINDENTSIZE 
         CurrentIndent = Space(Indent) 

         Line = CurrentIndent : '</SubRecord>' 
         WriteSeq Line To fOutputFile Then WriteCount += 1 Else WriteFailCount += 1 

      Next k 

      Indent -= XMLINDENTSIZE 
      CurrentIndent = Space(Indent) 

      Line = CurrentIndent : '</Collection>' 
      WriteSeq Line To fOutputFile Else NULL 

      Line = CurrentIndent : '<Property Name="SEQ-Delimiter">' : rDSMETADATA<39> : '</Property>' 
      WriteSeq Line To fOutputFile Else NULL 

      Line = CurrentIndent : '<Property Name="SEQ-QuoteChar">' : rDSMETADATA<40> : '</Property>' 
      WriteSeq Line To fOutputFile Else NULL 

      Line = CurrentIndent : '<Property Name="SEQ-ColHeaders">' : rDSMETADATA<41> : '</Property>' 
      WriteSeq Line To fOutputFile Else NULL 

      Line = CurrentIndent : '<Property Name="SEQ-FixedWidth">' : rDSMETADATA<42> : '</Property>' 
      WriteSeq Line To fOutputFile Else NULL 

      Line = CurrentIndent : '<Property Name="SEQ-ColSpace">' : rDSMETADATA<43> : '</Property>' 
      WriteSeq Line To fOutputFile Else NULL 

      Line = CurrentIndent : '<Property Name="SEQ=OmitNewLine">' : rDSMETADATA<44> : '</Property>' 
      WriteSeq Line To fOutputFile Else NULL 

      Line = CurrentIndent : '<Property Name="AllowColumnMapping">' : rDSMETADATA<45> : '</Property>' 
      WriteSeq Line To fOutputFile Else NULL 

      Line = CurrentIndent : '<Property Name="Locator">' : rDSMETADATA<54> : '</Property>' 
      WriteSeq Line To fOutputFile Else NULL 

      Line = CurrentIndent : '<Property Name="PadChar"/> 
      WriteSeq Line To fOutputFile Else NULL 

      Indent -= XMLINDENTSIZE 
      CurrentIndent = Space(Indent) 

      Line = CurrentIndent : '</Record>' 
      WriteSeq Line To fOutputFile Else NULL 

      Return(0)                             ; * end of DumpXML internal subroutine 



************************************************************ 
DelimitedHeader: 
************************************************************ 

      Begin Case 
         Case pDelimiter = "Tab" 
            cDelimiter = Char(9) 
         Case pDelimiter[1,5] = "Comma" 
            cDelimiter = "," 
         Case pDelimiter[1,4] = "Pipe" 
            cDelimiter = "|" 
         Case pDelimiter[1,5] = "Colon" 
            cDelimiter = ":" 
         Case pDelimiter[1,4] = "Semi" 
            cDelimiter = ";" 
         Case pDelimiter[1,8] = "Asterisk" 
            cDelimiter = "*" 
      End Case 

      If pHeaderLine = "Yes" And pOpenMode = "Overwrite" 
      Then 
         HeaderLine = "ColumnName" : cDelimiter : "SQLDataType" : cDelimiter : "Precision" : cDelimiter : "Scale" : cDelimiter : "IsNullable" : cDelimiter : "KeyColumn" : cDelimiter : "Description" 
         WriteSeq HeaderLine To fOutputFile Else NULL 
      End 

      Return(0)                             ; * end of DelimitedHeader internal subroutine 



************************************************************ 
IntegrityHeader: 
************************************************************ 

      * Provide default INTEGRITY project name if necessary. 
      If IsNull(pProjectName) Or Trim(pProjectName) = "" 
      Then 
         pProjectName = DSGetProjectInfo(DSJ.PROJECTNAME) 
      End 

      * Generate max record length for INTEGRITY format. 
      pMaxRecordLength = 0 
      For k = 1 To nColumns 
         If lDisplayWidth<k> = 0 
         Then 
            pMaxRecordLength += lPrecision<k> + lScale<k> 
         End 
         Else 
            pMaxRecordLength += lDisplayWidth<k> 
         End 
      Next k 

      * Generate dummy table description for INTEGRITY or XML format. 
      If (IsNull(lTableShortDesc) OR Trim(lTableShortDesc) = "") 
      Then 
         lTableShortDesc = "No Table Desc" 
      End 

      * Generate non-repeating portion of output file 
      WriteSeq "PROJECT BEGIN" To fOutputFile Else Call DSLogWarn("Problem writing to file", "DEBUG") 
      WriteSeq "  NAME                           ":pProjectName[1,8] To fOutputFile Else NULL 
      WriteSeq "  DESCRIPTION                    ":pProjectDescription[1,40] To fOutputFile Else NULL 
      WriteSeq " " To fOutputFile Else NULL 
      WriteSeq " " To fOutputFile Else NULL 
      WriteSeq " " To fOutputFile Else NULL 
      WriteSeq "  DATA_TABLE BEGIN" To fOutputFile Else NULL 


      Return(0)                             ; * end of IntegrityHeader internal subroutine 



************************************************************ 
IntegrityTrailer: 
************************************************************ 

      WriteSeq " " To fOutputFile Else NULL 
      WriteSeq "  END   #DATA_TABLE" To fOutputFile Else NULL 

      WriteSeq " " To fOutputFile Else NULL 
      WriteSeq "END   #PROJECT" To fOutputFile Else NULL 

      Return(0)                             ; * end of IntegrityTrailer internal subroutine 


************************************************************ 
IntegrityEOF:!!! Routine added in version 20.0.2 
************************************************************ 
* Remove "END #DATATABLE" and subsequent lines from existing file 

      Call !GET.PATHNAME(pOutputFile, TempDir, TempFile, Code) 

      OpenPath TempDir To fTemp 
      On Error 
         Message = 'Unable to open "' : TempDir : '".' 
         Call DSLogWarn(Message, "DumpColumnDefinitions") 
      End 
      Then 
         ReadU TempRecord From fTemp, TempFile 
         Locked 
            Message = Quote(pOutputFile) : " locked for update by another DataStage process." 
            Message<-1> = "   DataStage process number = " : Status() : "." 
            Call DSLogWarn(Message, "DumpColumnDefinitions") 
         End 
         Then 
            NewRecord = "" 
            Loop 
               Remove Element From TempRecord Setting MoreElements 
            While MoreElements And Not(Element Matches "0X'END'0X'#DATA_TABLE'0X") 
               NewRecord<-1> = Element 
            Repeat 
            Write NewRecord To fTemp, TempFile 
            Then 
               NULL 
            End 
         End 
         Else 
            Release fTemp, TempFile      ; * doesn't exist, so release update lock 
         End 
         Close fTemp 
      End 
      Else 
         Message = 'Unable to open "' : TempDir : '".' 
         Call DSLogWarn(Message, "DumpColumnDefinitions") 
      End 
      Return(0)                             ; * end of IntegrityEOF internal subroutine 



************************************************************ 
XMLHeader: 
************************************************************ 

      Indent = 0 

      WriteSeq '<?xml version="1.0" encoding="UTF-8"?>' To fOutputFile Else Null 
      WriteSeq '<DSExport>' To fOutputFile Else Null 

      Indent += XMLINDENTSIZE 
      CurrentIndent = Space(Indent) 

      Line = CurrentIndent : '<Header CharacterSet="ENGLISH" ExportingTool="Ascential DataStage" ToolVersion = "3"' 
      Line := ' ServerName="' : lServerName : '" ToolInstanceID="DumpColumnDefinitions" Date="' : Oconv(@DATE,"D-YMD[4,2,2]") 
      Line := '" Time = "' : Oconv(@TIME, "MTS:") : '"/>' 
      WriteSeq Line To fOutputFile Else Null 

      WriteSeq CurrentIndent : '<TableDefinitions>' To fOutputFile Else Null 

      Indent += XMLINDENTSIZE 
      CurrentIndent = Space(Indent) 

      Return(0)                             ; * end of XMLHeader internal subroutine 


************************************************************ 
XMLTrailer: 
************************************************************ 

      Indent -= XMLINDENTSIZE 
      CurrentIndent = Space(Indent) 

      WriteSeq CurrentIndent : '</TableDefinitions>' To fOutputFile Else Null 

      Indent -= XMLINDENTSIZE 

      WriteSeq '</DSExport>' To fOutputFile Else Null 

      Return(0)                             ; * end of XMLTrailer internal subroutine 



************************************************************ 
XMLEOF:!!! Routine added in version 20.0.2 
************************************************************ 
* Remove </TableDefinitions> and subsequent lines from existing file 

      Call !GET.PATHNAME(pOutputFile, TempDir, TempFile, Code) 

      OpenPath TempDir To fTemp 
      On Error 
         Message = 'Unable to open "' : TempDir : '".' 
         Call DSLogWarn(Message, "DumpColumnDefinitions") 
      End 
      Then 
         ReadU TempRecord From fTemp, TempFile 
         Locked 
            NULL 
         End 
         Then 
            NewRecord = "" 
            Loop 
               Remove Element From TempRecord Setting MoreElements 
            While MoreElements And Not(Element Matches "0X'</TableDefinitions>'0X") 
               NewRecord<-1> = Element 
            Repeat 
            Write NewRecord To fTemp, TempFile 
            Then 
               NULL 
            End 
         End 
         Else 
            Release fTemp, TempFile      ; * doesn't exist, so release update lock 
         End 
         Close fTemp 
      End 
      Else 
         Message = 'Unable to open "' : TempDir : '".' 
         Call DSLogWarn(Message, "DumpColumnDefinitions") 
      End 
      Return(0)                       ; * end of XMLEOF internal subroutine

RETURN(Ans)
IBM Software Services Group
Any contribution to this forum is my own opinion and does not necessarily reflect any position that IBM may hold.
Post Reply