Resources

Home   News   Version 1   Tech Support   Pubs   S2K Site Map



Using SYSTEM 2000 to Generate XML Documents


XML document generation using SYSTEM 2000 database data is now available through the Self-Contained Facility (SCF) PRINT command. PRINT is an SCF retrieval command that generates structured output for a group of components, a record, or a group of records. The output consists of the component number/name, a system separator, and the component's value.

Because the output from a PRINT command goes to the Report File, you can assign the Report File to a sequential data set and generate your XML document there. This sequential file in turn can be sent to a PC (or other platform) by using an FTP command.

PRINT Command Options

The PRINT command has several syntax options, such as NAME/NUMBER, REPEAT/REPEAT SUPPRESS, and NULL/NULL SUPPRESS. The defaults are NUMBER, REPEAT, and NULL SUPPRESS. If you want component numbers to identify components, then you use the default NUMBER. If you want to see only items that are valued, then you use the default NULL SUPPRESS.

Once an option has been specified, it remains in effect for the duration of a user session or until it is reset.

Two new options have been added to the PRINT command: XMLON and XMLOFF. XMLON generates PRINT command output as an XML document. This means there are start and end tags for the document identifier, and element tags for each component. Record start and end tags are inserted to group elements by record.

Normal PRINT command output:

PRINT C132 WH C1 EQ 1043:
	132* HUSBAND EMPLOYED AS INSTRUCTOR
	132* IN THE MARKETING DEPARTMENT
	132* NAME: GEORGE J. GIBSON
	132*     TEST    TEXT
---
EXIT:

Output from the same command with XMLON specified:

PRINT /XMLON/ C132 WH C1 EQ 1043:
<S2K_EMPLOYEE>
	<C130>

	<C132> HUSBAND EMPLOYED AS INSTRUCTOR</C132>
	<C132> IN THE MARKETING DEPARTMENT   </C132>
	<C132> NAME: GEORGE J. GIBSON</C132>
	<C132>     TEST    TEXT      </C132>

<C130>

<S2K_EMPLOYEE>
---

The same command with the NAME option:

PRINT /NAME,XMLON/ C132 WH C1 EQ 1043:
<S2K_EMPLOYEE>
     	<ADDITIONAL_INFORMATION>

     	<COMMENT_TEXT> HUSBAND EMPLOYED AS INSTRUCTOR   </COMMENT_TEXT>
   	<COMMENT_TEXT> IN THE MARKETING DEPARTMENT  </COMMENT_TEXT>
   	<COMMENT_TEXT> NAME: GEORGE J. GIBSON   </COMMENT_TEXT>
   	<COMMENT_TEXT>     TEST    TEXT     </COMMENT_TEXT>

</ADDITIONAL_INFORMATION>

<S2K_EMPLOYEE>
---
Blanks and Nulls

The above commands are printing a component defined in the database as a text item. A text item retains the white space, or blanks, before and after the value. Some XML translators remove this white space before the value is displayed but SYSTEM 2000 leaves all data in place for a text item.

SYSTEM 2000 supports the concept of a "null" value occurring in a database. A PRINT command with the /NULL/ option displays a null value as follows:

PRINT /NAME, NULL/ C0 WH C1 EQ 1043:
.
END DATE* -NULL-
.

When this -NULL- character string is found, an empty element is generated that looks like this:

PRINT /NAME, NULL,XMLON/ C0 WH C1 EQ 1043:
.
<END_DATE/>
.

SYSTEM 2000 tries to determine if a -NULL- value is because of the NULL option being on or if it is a real database value. If the NULL SUPPRESS option is on, -NULL- is not eliminated as an element value. If the NULL option is on, SYSTEM 2000 cannot tell the difference between a generated -NULL- value and a real -NULL- value so it turns all of these values into empty elements.

Data Hierarchy and REPEAT SUPPRESS Option

SYSTEM 2000 also allows the user to display the PRINT output in a format that resembles a relational table. The REPEAT option (the default) makes this happen and it looks like this:

PRINT /NAME/ C1,C201 WH C1 EQ 1043:
EMPLOYEE NUMBER*  1043
   SKILL TYPE* GRAPHICS
EMPLOYEE NUMBER*  1043
   SKILL TYPE* CARTOON ART
---

In the above output, the EMPLOYEE NUMBER component is displayed for each occurrence of the lower-level SKILL TYPE component.

The same command with XML output:

PRINT /NAME,XMLON/ C1,C201 WH C1 EQ 1043:

<?xml version='1.0' standalone='yes'?>
<S2K_EMPLOYEE>
<ENTRY>

<EMPLOYEE_NUMBER>  1043 </EMPLOYEE_NUMBER>
   <SKILL_TYPE> GRAPHICS</SKILL_TYPE>
<EMPLOYEE_NUMBER>  1043 </EMPLOYEE_NUMBER>
   <SKILL_TYPE> CARTOON ART</SKILL_TYPE>

</ENTRY>

</S2K_EMPLOYEE>
---

The same command using the REPEAT SUPPRESS option:

					
PRINT /NAME,REPEAT SUPPRESS/ C1,C201 WH C1 EQ 1043:
EMPLOYEE NUMBER*  1043
 SKILL TYPE* GRAPHICS
 SKILL TYPE* CARTOON ART
---

In the above output, the EMPLOYEE NUMBER component is only displayed once and its two lower-level SKILL TYPE components displayed below it.

The same command with XML output:

PRINT /NAME,REPEAT SUPPRESS,XMLON/ C1,C201 WH C1 EQ 1043:
  
<?xml version='1.0' standalone='yes'?>
<S2K_EMPLOYEE>
<ENTRY>

<EMPLOYEE_NUMBER>  1043 </EMPLOYEE_NUMBER>
    <SKILL_TYPE> GRAPHICS</SKILL_TYPE>
    <SKILL_TYPE> CARTOON ART</SKILL_TYPE>

</ENTRY>

</S2K_EMPLOYEE>
---

With the REPEAT option on in the above example, it is impossible to tell in the resulting document if there are two EMPLOYEE_NUMBER components with one SKILL_TYPE component each or if there is one EMPLOYEE_NUMBER component with two SKILL_TYPE components. Because of this anomaly, it is advisable to use the REPEAT SUPPRESS option so that the hierarchical structure of the data is maintained.

Special Characters

Note that the XML tag names don't always exactly match the component names generated in the PRINT output (SKILL_TYPE as opposed to SKILL TYPE). XML reserves some special characters for use as XML syntax markers. The main ones to be concerned about are the space ( ), ampersand (&), less than (<), greater than (>), apostrophe ('), and quote("). Because you can't have any of these characters in a tag name, or directly in a data value, part of the process of reformatting the PRINT output for XML output is to replace these characters with something else. In the case of tag names, all of the above-mentioned characters are replaced with the underscore (_). In element values, these characters are replaced with one of the predefined entities '&amp;', '&lt;', '&gt;', '&apos;', and '&quot;'.

Element Name Replacement

In building XML output, the component names from the database are used as the XML element nametags. If for some reason you don't want to use these names you can generate a sequential file that contains replacement names. The DD card for this file must be included in the JCL used to start your SYSTEM 2000 session and must be named XREPLACE. This file is read prior to tag generation and database component names are replaced with your chosen user names. The file characteristics must be as follows:

-- The file must be defined with a record length of 80. Anything past 80 bytes in a record is ignored. You can generate comments in the file using the following structure:

/* This is a comment and will be ignored during table building */  

Comments can span multiple lines in the file but must be started with a '/*' and terminated with a '*/'.

-- The first non-comment line in the file must be a database identifier line. This line must be formatted as follows:

	DBN=xxxxxxxxxxxxxxxx

where xxxxxxxxxxxxxxxx is the name of a SYSTEM 2000 database from 1 to 16 characters long.

example:
DBN=EMPLOYEE

This line indicates that for the EMPLOYEE database, the ensuing name replacements are valid.

-- Immediately after this line, you must start the name replacement identifiers. On each line you must have the name you want to replace, followed by a comma, then the name you want to replace it with. You can only have one name pair per record and the name pair must fit in one record. You can start the name pair anywhere on the card, but once started, there can be no extraneous blanks. Any blanks found from the start of the old name to the end of the new name are replaced with underscore characters (_) and become part of the name.

-- The name to be replaced can be specified as either the database component name (EMPLOYEE NUMBER), the valid XML element name (EMPLOYEE_NUMBER), or the component number (if you don't use the NAME option on the PRINT command). If you do not use the NAME option on your PRINT command, the component identifier will be the external component number preceded by a 'C' (as in C1, C2, etc.). Examples of table entries are as follows:

DBN=EMPLOYEE
EMPLOYEE NUMBER,EMPNO
SOCIAL_SECURITY_NUMBER,SSN
BIRTHDAY,DATE OF BIRTH
C1,EMPNO
C7,SSN
C6,DATE OF BIRTH

Remember, no blanks are permitted on either side of the separating comma.

In the above example, the replacement name 'DATE OF BIRTH' is not valid for an XML element name. It would be changed to 'DATE_OF_BIRTH' before being used as an element tag.

To summarize, your whole file might look something like the following:

/* This is the name replacement table for the EMPLOYEE database */
DBN=EMPLOYEE
EMPLOYEE NUMBER,EMPNO
SOCIAL_SECURITY_NUMBER,SSN
/* White space in either name will be replaced with
    underscore characters */
BIRTHDAY,DATE OF BIRTH

If you want to specify name replacement values for multiple databases, your file might look something like this:

DBN=EMPLOYEE
EMPLOYEE NUMBER,EMPNO
BIRTHDAY,DATE OF BIRTH
DBN=PERSONNEL
BIRTH DATE,DATE OF BIRTH
DBN=LIBRARY
AUTHOR TAG, AUTHOR

In the above example, the EMPLOYEE NUMBER and the BIRTHDAY component names are replaced only for the EMPLOYEE database, the BIRTH DATE component name is replaced only for the PERSONNEL database, and so forth.

Sample Replacement Table JCL

The replacement table can be either a sequential data set or a member of a PDS. You can set up a PDS member for each database and concatenate the members in the JCL. That might look something like the following:

	//XREPLACE  DD  DSN=MYDSN.SOURCE(XMLEMP),DISP=SHR
	//          DD  DSN=MYDSN.SOURCE(XMLLIB),DISP=SHR
	//          DD  DSN=MYDSN.SOURCE(XMLPERS),DISP=SHR

where XMLEMP contains the replacement name table for the EMPLOYEE database, XMLLIB contains the replacement name table for the LIBRARY database, and XMLPERS contains the replacement name table for the PERSONNEL database.

When an XREPLACE DD card is recognized, SYSTEM 2000 issues a WTO indicating the table build is starting:

S2K0300/00- GENERATING XML NAME REPLACEMENT TABLE

In the event that the first non-comment line in the XREPLACE file is not a DBN= line, the following WTO is issued:

S2K0301/00- THE FIRST PARSED LINE IN XREPLACE IS NOT DBN=

Parsing continues at the next DBN= line.

If errors are found on a name replacement line, this WTO is issued:

S2K0302/00- ERROR IN LINE# nnn FOR DATABASE XXXXXXXXXXXXXXX

where nnn is the relative line number where the error occurred and

xxxxxxxxxxxxxxx is the database name the line is associated with.

In there is an I/O error on the the replacement file, this WTO is issued:

S2K0303/00- ERROR ENCOUNTERED ACCESSING XREPLACE FILE

If the getmain for the internal replacement table fails, this WTO is issued:

S2K0304/00- GETMAIN FAILED FOR INTERNAL XML NAME TABLE

If the XREPLACE file is empty, this WTO is issued:

S2K0305/00- THE XREPLACE FILE HAS NO RECORDS

The first error in a given database replacement list causes the entire list for that database to be thrown away. Parsing of the file continue at the next DBN= line. If there are multiple databases in the file and only one has an error, the table is built for the rest of the databases. If there are multiple databases and more than one has an error, you receive multiple 302 WTO's.

XMLCHECK Utility

A stand-alone utility that parses an XREPLACE file and reports errors is called XMLCHECK. Unlike the internal table build routine, the utility does not stop processing at the first error but identifies all error conditions in the file. The errors are identified by displaying the line in error, followed by a message indicating the kind of error encountered, such as:

In each error condition, the line in error is displayed immediately before the error message, like this:

EMPLOYEE_NUMBER,EMPNO
*ERROR* THE FIRST PARSED LINE IN THE FILE IS NOT DBN=

or

EMPLOYEE_NUMBER EMPNO
*ERROR* NO REPLACEMENT NAME SPECIFIED

(missing comma between EMPLOYEE_NUMBER and EMPNO)

or

DBN=MY DATABASE NUMBER 1
*ERROR* THE SUPPLIED DATABASE NAME EXCEEDS 16 CHARACTERS

The entire replacement name file is parsed and a report generated at the end that lists the names of all of the databases identified in the file. A warning report is also generated for replacement names that do not fit the requirements for an XML tag name. An example of that is:

in the file;

BIRTHDAY,DATE OF BIRTH
EMPLOYEE_NUMBER,EMP&NUMB

the warnings;

*WARN* DATE OF BIRTH WILL BE CHANGED TO DATE_OF_BIRTH
*WARN* EMP&NUMB WILL BE CHANGED TO EMP_NUMB
Sample JCL for XMLCHECK

The following is a sample job for running the XMLCHECK stand-alone utility:

	//XMLCHECK JOB
	//STEP1    EXEC PGM=XMLCHECK
	//STEPLIB  DD	 DSN=MYDSN.LOAD,DISP=SHR
	//XREPLACE DD	 DSN=MYDSN.REPLACE,DISP=SHR
	//PRINT    DD SYSOUT=*