Rational Developer for System z
Enterprise PL/I for z/OS, Version 4.1, Programming Guide

Example of using the PLISAXD built-in subroutine

The following example illustrates the use of the PLISAXD built-in subroutine and uses the example XML document and the XML schema cited in the previous examples.

This example includes the validation of 8 different XML files against the same stock.osr schema. In the following output, you can see which XML documents in the saxdtest program fail validation against the schema.

The PLISAXD built-in subroutine requires the XML schema file to be read into a buffer. The OSR file in the following example is in a PDS. The initial size of the OSR buffer is set to 4096. If you have a larger OSR file, you can increase the initial size of the OSR buffer accordingly.

If the inbound schema file were in an HFS file instead, you could use the following code to read the OSR file into the buffer:

dcl osrin file input stream environment(u);
dcl fileddint builtin;
dcl fileread builtin;

/* Read the HFS OSR file into buffer*/

open file(osrin);
osr_length = fileddint( osrin, 'filesize');
osr_ptr = allocate(osr_length);
rc = fileread(osrin,osr_ptr,osr_length);

To run a program by using an OSR in a PDS, you can specify the following DD statement in the JCL:

//OSRIN DD DSN=HLQ.XML.OSR(STOCK),DISP=SHR

If the associated ddname OSRIN is an HFS file, then use the following JCL statement instead:

//OSRIN DD PATH="/u/HLQ/xml/stock.osr"
Figure 101. PLISAXD coding example - event routines
  saxdtest: package exports(saxdtest);
    /************************************************************/
    /* saxdtest: Test PL/I XML validation support               */
    /* expected output:                                         */
    /*                                                          */
    /*   SAXDTEST: PL/I XML Validation sample                   */
    /*   SAXDTEST: Document Successfully parsed                 */
    /*   SAXDTEST: Document Successfully parsed                 */
    /*   Invalid: missing attribute itemNumber.                 */
    /*   exception return_code =00000018, reason_code =8613     */
    /*   Invalid: unexpected attribute warehouse.               */
    /*   exception return_code =00000018, reason_code =8612     */
    /*   Invalid: illegal attribute value 123-Ab.               */
    /*   exception return_code =00000018, reason_code =8809     */
    /*   Invalid: missing element quantityOnHand.               */
    /*   exception return_code =00000018, reason_code =8611     */
    /*   Invalid: unexpected element comment.                   */
    /*   exception return_code =00000018, reason_code =8607     */
    /*   Invalid: out-of-range element value 100                */
    /*   exception return_code =00000018, reason_code =8803     */
    /*                                                          */
    /************************************************************/

    define alias event
        limited entry( pointer, pointer, fixed bin(31) )
        returns( byvalue fixed bin(31) )
        options( byvalue linkage(optlink) );

    define alias event_with_flag
        limited entry( pointer, pointer, fixed bin(31),
                       bit(8) aligned )
        returns( byvalue fixed bin(31) )
        options( nodescriptor byvalue linkage(optlink) );
    define alias event_with_namespace
        limited entry( pointer, pointer, fixed bin(31),
                       pointer, fixed bin(31),
                       pointer, fixed bin(31) )
        returns( byvalue fixed bin(31) )
        options( byvalue linkage(optlink) );

    define alias event_without_data
        limited entry( pointer )
        returns( byvalue fixed bin(31) )
        options( byvalue linkage(optlink) );

    define alias event_pi
        limited entry( pointer, pointer, fixed bin(31),
                       pointer, fixed bin(31) )
        returns( byvalue fixed bin(31) )
        options( byvalue linkage(optlink) );

    define alias event_namespace_dcl
        limited entry( pointer, pointer, fixed bin(31),
                       pointer, fixed bin(31) )
        returns( byvalue fixed bin(31) )
        options( byvalue linkage(optlink) );

    define alias event_exception
        limited entry( pointer, fixed bin(31),
                       fixed bin(31),
                       fixed bin(31) )
        returns( byvalue fixed bin(31) )
        options( byvalue linkage(optlink) );

    define alias event_end_of_input
        limited entry( pointer,
                       pointer byaddr,
                       fixed bin(31) byaddr )
        returns( byvalue fixed bin(31) )
        options( byvalue linkage(optlink) );
  saxdtest: proc options( main );

    dcl
      1 eventHandler static

        ,2 e01 type event_without_data
               init( start_of_document )

        ,2 e02 type event
               init( version_information )

        ,2 e03 type event
               init( encoding_declaration )

        ,2 e04 type event
               init( standalone_declaration )

        ,2 e05 type event
               init( document_type_declaration )

        ,2 e06 type event_without_data
               init( end_of_document )

        ,2 e07 type event_with_namespace
               init( start_of_element )

        ,2 e08 type event_with_namespace
               init( attribute_name )

        ,2 e09 type event
               init( attribute_characters )

        ,2 e10 type event_with_namespace
               init( end_of_element )

        ,2 e11 type event_without_data
               init( start_of_CDATA )

        ,2 e12 type event_without_data
               init( end_of_CDATA )

        ,2 e13 type event_with_flag
               init( content_characters )

        ,2 e14 type event_pi
               init( processing_instruction )

        ,2 e15 type event
               init( comment )

        ,2 e16 type event_namespace_dcl
               init( namespace_declare )

        ,2 e17 type event_end_of_input
               init( end_of_input )

        ,2 e18 type event
               init( unresolved_reference )

        ,2 e19 type event_exception
               init( exception )
        ;
    dcl token       char(45);

    dcl rc             fixed bin(31);
    dcl i              fixed bin(31);
    dcl xml_document(8) char(300) var;
    dcl xml_valid_msg(8) char(45) var;
    dcl osr_ptr        pointer;
    dcl record         char(80);
    dcl osr_index      fixed bin;
    dcl osr_buf_tail   fixed bin;
    dcl temp_osr       pointer;
    dcl buf_size       fixed bin(31) init(4096);
    dcl rec_size       fixed bin(31);
    dcl osr_length     fixed bin(31);
    dcl buf_length     fixed bin(31);
    dcl eof fixed      bin(31) init(0);
    dcl osrin          file input;

    on endfile(osrin) begin;
      eof = 1;
    end;

    /* read the entire PDS osr file into the buffer */

    put skip list ('SAXDTEST: PL/I XML Validation sample ');

    osr_length = buf_size;
    osr_index = 0;
    osr_buf_tail = 0;
    rec_size = length(record);

    osr_ptr = allocate(osr_length);

    do while (eof = 0 );

      read file(osrin) into(record);
      osr_buf_tail += rec_size;
      if osr_buf_tail > buf_size then
        do;
          buf_length = osr_length;
          osr_length +=buf_size;
          temp_osr = allocate(osr_length);

          call plimove(temp_osr, osr_ptr, buf_length);
          call plifree(osr_ptr);
          osr_ptr = temp_osr;
          osr_buf_tail = rec_size;

          call plimove(osr_ptr+osr_index, addr(record), rec_size);
          osr_index += rec_size;
        end;
      else
        do;
          call plimove(osr_ptr+osr_index, addr(record), rec_size);
          osr_index  +=rec_size;
        end;

    end;
    /* Valid XMLFILE */
    xml_document(1) = '<stockItem itemNumber="453-SR">'
    || '<itemName>Stainless steel rope thimbles</itemName>'
    || '<quantityOnHand>23</quantityOnHand>'
    || '</stockItem>';

    xml_valid_msg(1) = 'Valid XMLFILE ';
    /* Valid: the ITEMNAME element can be omitted */
    xml_document(2) = '<stockItem  itemNumber="453-SR">'
    || '<quantityOnHand>23</quantityOnHand>'
    || '</stockItem>';

    xml_valid_msg(2) = 'Valid: the ITEMNAME element can be omitted.';

    /* Invalid: missing attribute itemNumber */
    xml_document(3) = '<stockItem>'
    || '<itemName>Stainless steel rope thimbles</itemName>'
    || '<quantityOnHand>23</quantityOnHand>'
    || '</stockItem>';

    xml_valid_msg(3) = 'Invalid: missing attribute itemNumber.';

    /* Invalid: unexpected attribute warehouse */
    xml_document(4) = '<stockItem itemNumber="453-SR" warehouse="NY">'
    || '<itemName>Stainless steel rope thimbles</itemName>'
    || '<quantityOnHand>23</quantityOnHand>'
    || '</stockItem>';

    xml_valid_msg4) = 'Invalid: unexpected attribute warehouse.';

    /* Invalid: illegal attribute value 123-Ab */
    xml_document(5) = '<stockItem itemNumber="123-Ab">'
    || '<itemName>Stainless steel rope thimbles</itemName>'
    || '<quantityOnHand>23</quantityOnHand>'
    || '</stockItem>';

    xml_valid_msg(5) = 'Invalid: illegal attribute value 123-Ab.';

    /* Invalid: missing element quantityOnHand */
    xml_document(6) = '<stockItem itemNumber="074-UN">'
    || '<itemName>Stainless steel rope thimbles</itemName>'
    || '</stockItem>';

    xml_valid_msg(6) = 'Invalid: missing element quantityOnHand.';

    /* Invalid: unexpected element comment */
    xml_document(7) = '<stockItem itemNumber="453-SR">'
    || '<itemName>Stainless steel rope thimbles</itemName>'
    || '<quantityOnHand>1</quantityOnHand>'
    || '<commnet>Nylon bristles</comment>'
    || '</stockItem>';

    xml_valid_msg(7) = 'Invalid: unexpected element comment.';

    /* Invalid: out-of-range element value 100 */
    xml_document(8) = '<stockItem itemNumber="123-AB">'
    || '<itemName>Paintbrush</itemName>'
    || '<quantityOnHand>100</quantityOnHand>'
    || '</stockItem>';

    xml_valid_msg(8) = 'Invalid: out-of-range element value 100';
    do i = 1 to hbound(xml_document);;
      token = xml_valid_msg(i);
      call plisaxd( eventHandler,
                    addr(token),
                    addrdata(xml_document(i)),
                    length(xml_document(i)),
                    osr_ptr,
                    37 );
    end;

    close file(osrin);
    call plifree(osr_ptr);

  end;

  start_of_document:
    proc( userToken )
    returns( byvalue fixed bin(31) )
    options( byvalue linkage(optlink) );

    dcl userToken      pointer;

    return(0);
  end;

  version_information:
    proc( userToken, xmlToken, TokenLength )
    returns( byvalue fixed bin(31) )
    options( byvalue linkage(optlink) );

    dcl userToken      pointer;
    dcl xmlToken       pointer;
    dcl tokenLength    fixed bin(31);


    return(0);
  end;

  encoding_declaration:
    proc( userToken, xmlToken, TokenLength )
    returns( byvalue fixed bin(31) )
    options( byvalue linkage(optlink) );

    dcl userToken      pointer;
    dcl xmlToken       pointer;
    dcl tokenLength    fixed bin(31);


    return(0);
  end;

  standalone_declaration:
    proc( userToken, xmlToken, TokenLength )
    returns( byvalue fixed bin(31) )
    options( byvalue linkage(optlink) );

    dcl userToken      pointer;
    dcl xmlToken       pointer;
    dcl tokenLength    fixed bin(31);

    return(0);
  end;
  document_type_declaration:
    proc( userToken, xmlToken, TokenLength )
    returns( byvalue fixed bin(31) )
    options( byvalue linkage(optlink) );

    dcl userToken      pointer;
    dcl xmlToken       pointer;
    dcl tokenLength    fixed bin(31);


    return(0);
  end;

  end_of_document:
    proc( userToken )
    returns( byvalue fixed bin(31) )
    options( byvalue linkage(optlink) );

    dcl userToken      pointer;

    put skip list( 'SAXDTEST: Document Successfully parsed ');

    return(0);
  end;

  start_of_element:
    proc( userToken, xmlToken, TokenLength,
          nsPrefix, nsPrefixLength,
          nsUri, nsUriLength )
    returns( byvalue fixed bin(31) )
    options( byvalue linkage(optlink) );

    dcl userToken      pointer;
    dcl xmlToken       pointer;
    dcl tokenLength    fixed bin(31);
    dcl nsPrefix       pointer;
    dcl nsPrefixLength fixed bin(31);
    dcl nsUri          pointer;
    dcl nsUriLength    fixed bin(31);

    return(0);
  end;
  attribute_name:
    proc( userToken, xmlToken, tokenLength,
          nsPrefix, nsPrefixLength,
          nsUri, nsUriLength )
    returns( byvalue fixed bin(31) )
    options( byvalue linkage(optlink) );

    dcl userToken      pointer;
    dcl xmlToken       pointer;
    dcl tokenLength    fixed bin(31);
    dcl nsPrefix       pointer;
    dcl nsPrefixLength fixed bin(31);
    dcl nsUri          pointer;
    dcl nsUriLength    fixed bin(31);

    return(0);
  end;

  attribute_characters:
    proc( userToken, xmlToken, TokenLength )
    returns( byvalue fixed bin(31) )
    options( byvalue linkage(optlink) );

    dcl userToken      pointer;
    dcl xmlToken       pointer;
    dcl tokenLength    fixed bin(31);

    return(0);
  end;

  end_of_element:
    proc( userToken, xmlToken, TokenLength,
          nsPrefix, nsPrefixLength,
          nsUri, nsUriLength )
    returns( byvalue fixed bin(31) )
    options( byvalue linkage(optlink) );

    dcl userToken      pointer;
    dcl xmlToken       pointer;
    dcl tokenLength    fixed bin(31);
    dcl nsPrefix       pointer;
    dcl nsPrefixLength fixed bin(31);
    dcl nsUri          pointer;
    dcl nsUriLength    fixed bin(31);

    return(0);
  end;

  start_of_CDATA:
    proc( userToken )
    returns( byvalue fixed bin(31) )
    options( byvalue linkage(optlink) );

    dcl userToken      pointer;


    return(0);
  end;
  end_of_CDATA:
    proc( userToken )
    returns( byvalue fixed bin(31) )
    options( byvalue linkage(optlink) );

    dcl userToken      pointer;

    return(0);
  end;

  content_characters:
    proc( userToken, xmlToken, TokenLength, flags )
    returns( byvalue fixed bin(31) )
    options( nodescriptor, byvalue linkage(optlink) );

    dcl userToken      pointer;
    dcl xmlToken       pointer;
    dcl tokenLength    fixed bin(31);
    dcl flags          bit(8) aligned;

    if flags = ''b then;
    else

    return(0);
  end;

  processing_instruction:
    proc( userToken, piTarget, piTargetLength,
                              piData, piDataLength )
    returns( byvalue fixed bin(31) )
    options( byvalue linkage(optlink) );

    dcl userToken      pointer;
    dcl piTarget       pointer;
    dcl piTargetLength fixed bin(31);
    dcl piData         pointer;
    dcl piDataLength   fixed bin(31);

    return(0);
  end;

  comment:
    proc( userToken, xmlToken, TokenLength )
    returns( byvalue fixed bin(31) )
    options( byvalue linkage(optlink) );

    dcl userToken      pointer;
    dcl xmlToken       pointer;
    dcl tokenLength    fixed bin(31);

    return(0);
  end;
  namespace_declare:
    proc( userToken, nsPrefix, nsPrefixLength,
                     nsUri, nsUriLength )
    returns( byvalue fixed bin(31) )
    options( byvalue linkage(optlink) );

    dcl userToken      pointer;
    dcl nsPrefix       pointer;
    dcl nsPrefixLength fixed bin(31);
    dcl nsUri          pointer;
    dcl nsUriLength    fixed bin(31);

    return(0);
  end;

  unresolved_reference:
    proc( userToken, xmlToken, TokenLength )
    returns( byvalue fixed bin(31) )
    options( byvalue linkage(optlink) );

    dcl userToken      pointer;
    dcl xmlToken       pointer;
    dcl tokenLength    fixed bin(31);

    return(0);
  end;

  exception:
    proc( userToken, currentOffset, return_code, reason_code )
    returns( byvalue fixed bin(31) )
    options( byvalue linkage(optlink) );

    dcl userToken      pointer;
    dcl currentOffset  fixed bin(31);
    dcl return_code    fixed bin(31);
    dcl reason_code    fixed bin(31);
    dcl validmsg       char(45) based;

    put skip list( userToken -> validmsg);
    put skip list( lowercase( procname() )
     || ' return_code =' || hex(return_code)
     || ', reason_code =' || substr(hex(reason_code),5,4));

    return(0);
  end;

  end_of_input:
    proc( userToken, addr_xml, length_xml )
    returns( byvalue fixed bin(31) )
    options( byvalue linkage(optlink) );

    dcl userToken      pointer;
    dcl addr_xml       byaddr pointer;
    dcl length_xml     byaddr fixed bin(31);

    return(0);
  end;

The following output shows the result of the sample program. For those documents that are not valid, the PLISAXD built-in subroutine invokes the XML exception event with the return code and reason code listed. For a detailed description of each return code and reason code, see XML System Services User's Guide and Reference.

Figure 102. Output from PLISAXD sample
SAXDTEST: PL/I XML Validation sample              
SAXDTEST: Document Successfully parsed            
SAXDTEST: Document Successfully parsed            
Invalid: missing attribute itemNumber.            
exception return_code =00000018, reason_code =8613
Invalid: unexpected attribute warehouse.          
exception return_code =00000018, reason_code =8612
Invalid: illegal attribute value 123-Ab.          
exception return_code =00000018, reason_code =8809
Invalid: missing element quantityOnHand.          
exception return_code =00000018, reason_code =8611
Invalid: unexpected element comment.              
exception return_code =00000018, reason_code =8607
Invalid: out-of-range element value 100           
exception return_code =00000018, reason_code =8803 

Terms of use | Feedback

This information center is powered by Eclipse technology. (http://www.eclipse.org)