XML-SAX 命令の例

図 389. 自由形式演算での XML-SAX 命令
D xmlString       S               C    '<?xml version="1.0"> +
D                                      <elem>data</elem>'
D psds            DS
D   xmlRc                       10I 0  OVERLAY(psds:368)
 /free
   // The XML is in an IFS file.  The "option" operand of %XML specifies
   // that the document operand is the name of an IFS file.
   XML-SAX %HANDLER(mySaxHandler : myHandlerInfo)
           %XML('/home/myuserid/myxml.xml' : 'doc=file');

   // The XML is in a string.  The "option" operand of %XML is not specified.
   XML-SAX %HANDLER(mySaxHandler : myHandlerInfo) %XML(xmlString);
図 390. 固定形式演算での XML-SAX 命令
CL0N01Factor1+++++++Opcode&ExtExtended-Factor2+++++++++++++++++++++++++
C                   XML-SAX   %HANDLER(mySaxHandler : myHandlerInfo)
C                             %XML('/home/myuserid/myxml.xml' : 'doc=file')

C                   XML-SAX   %HANDLER(mySaxHandler : myHandlerInfo)
C                             %XML(xmlString)
図 391. XML-SAX 処理プロシージャーを説明する、完全な作動プログラム
H DEBUG(*XMLSAX)
Fqsysprt   o    f  132        printer

 * The xmlRc subfield will be set to a non-zero value
 * if the XML-SAX operation fails because of an error
 * discovered by the parser

D psds           SDS
D   xmlRc
 [1]                    10I 0  OVERLAY(psds:368)

D qsysprtDs       DS           132

 * This data structure defines the type for the parameter
 * passed to the SAX handling procedure.
 [2] 
D value_t         S             50A    VARYING
D handlerInfo_t   DS                   QUALIFIED
D                                      BASED(dummy)
D   pValue                        *
D   numAttendees                 5P 0
D   name                               LIKE(value_t)
D   company                            LIKE(value_t)
D   alwExtraAttr                 1N
D   handlingAttrs...
D                                 N

 * Define a specific instance of the handlerInfo_t data
 * structure and the prototype for the handler
D myHandlerInfo   DS                   LIKEDS(handlerInfo_t)
D mySaxHandler    PR            10I 0
D   info                               LIKEDS(handlerInfo_t)
D   event                       10I 0  VALUE
D   stringPtr                     *    VALUE
D   stringLen                   20I 0  VALUE
D   exceptionId                 10I 0  VALUE


/free
     monitor;
        // Start XML parsing
        // Indicate that the handler should not allow
        // any unexpected attributes in the XML elements.
        myHandlerInfo.alwExtraAttr = *OFF;

 [3]   XML-SAX %HANDLER(mySaxHandler : myHandlerInfo)
           %XML('/home/myuserid/myxml.xml' : 'doc=file');
        // The XML parse completed normally
        // Results are passed back in the communication
        // area specified by the %HANDLER built-in function
        qsysprtDs = 'There are '
                  + %CHAR(myHandlerInfo.numAttendees)
                  + ' attendees.';
     on-error 00351;
        // The XML parse failed with a parser error.
        // The return code from the parser is in the PSDS.
        qsysprtDs = 'XML parser error: rc='
                  + %CHAR(xmlRc)
                  + '.';
     endmon;

        write qsysprt qsysprtDs;
     *inlr = '1';
 /end-free

P mySaxHandler    B
D                 PI            10I 0
D   info                               LIKEDS(handlerInfo_t)
D   event                       10I 0  VALUE
D   stringPtr                     *    VALUE
D   stringLen                   20I 0  VALUE
D   exceptionId                 10I 0  VALUE

D value           S                    LIKE(value_t)
D                                      BASED(info.pValue)

D chars           S          65535A    BASED(stringPtr)
D ucs2            S          16383C    BASED(stringPtr)
D ucs2Len         S             10I 0

/free

  select;

    // start parsing
    when event = *XML_START_DOCUMENT;
 [4]       clear info;

    // start processing an attendee, by indicating
    // that subsequent calls to this procedure should
    // handle XML-attribute events.
    when event = *XML_START_ELEMENT;
      if %subst(chars : 1 : stringLen) = 'attendee';
         info.handlingAttrs = *ON;
 [5]          info.name = '';
         info.company = '';
         info.numAttendees += 1;
      endif;

    // display information about the attendee
    when event = *XML_END_ELEMENT;
      if %subst(chars : 1 : stringLen) = 'attendee';
         info.handlingAttrs = *OFF;
         qsysprtDs = 'Attendee '
                   + info.name
                   + ' is from company '
                   + info.company;
        write qsysprt qsysprtDs;
      endif;

    // prepare to get an attribute value by setting
    // a basing pointer to the address of the correct
    // variable to receive the value
    when event = *XML_ATTR_NAME;
      if info.handlingAttrs;
        if %subst(chars : 1 : stringLen) = 'name';
           info.pValue = %addr(info.name);
        elseif %subst(chars : 1 : stringLen) = 'company';
           info.pValue = %addr(info.company);
         else;
           // If the XML element is not expected to have
           // extra attributes, halt the parsing by
           // returning -1.
           if not info.alwExtraAttr;
              qsysprtDs = 'Unexpected attribute '
                        + %subst(chars : 1 : stringLen)
                        + ' found.';
        write qsysprt qsysprtDs;
              return -1;
 [6]      endif;
           info.pValue = *NULL;
     endif;
      endif;

    // handle an exception
    when event = *XML_EXCEPTION;
        qsysprtDs = 'Exception '
                  + %char(exceptionId)
                  + ' occurred.';
        write qsysprt qsysprtDs;
        return exceptionId;

    other;

      // If this is an attribute we are interested
      // in, the basing pointer for "value" has been
      // set to point to either "name" or "company"

      // Append each fragment of the value to the
      // current data
      if  info.handlingAttrs
      and info.pValue <> *NULL;
        if event = *XML_ATTR_CHARS
        or event = *XML_ATTR_PREDEF_REF;
           value += %subst(chars : 1 : stringLen);
        elseif event = *XML_ATTR_UCS2_REF;
           ucs2Len = stringLen / 2;

 [7]     value += %char(%subst(ucs2 : 1 : ucs2Len));
        endif;
     endif;
    endsl;

    return 0;
 [8]  /end-free
P mySaxHandler    E

この例では、SAX 構文解析のいくつかの機能を説明しています。

  1. これは、xmlRc という名前の PSDS の「外部戻りコード」サブフィールド。
  2. 通信域データ構造、XML-SAX 命令と SAX イベント処理プロシージャーの間の通信に使用される。
  3. XML-SAX 命令が XML 文書の構文解析を開始。
  4. SAX イベント処理プロシージャーが、イベント・パラメーターを特殊名 *XML_START_DOCUMENT などと比較。
  5. 通信域は、イベント処理プロシージャーが自身と呼び出しの間に通信するためにも使用される。
  6. イベント処理プロシージャーがエラーを発見し、-1 を戻して構文解析を停止。
  7. *XML_ATTR_UCS2_REF イベントには、通常はこの XML-SAX 命令がデータを戻す場合に使用する CCSID とは無関係に、UCS-2 データがある。 長さはデータのバイト数を表すため、UCS-2 文字の数を取得するには、それを 2 で除算する必要があります。
  8. イベント処理プロシージャーは、エラーを発見しなかった場合には 0 を戻し、構文解析が継続可能であることを示す。

この例では、以下の XML 文書のサンプルを使用できます。

<meeting>
  <attendee name="Jack" company="A&amp;B Electronics"/>
  <attendee company="City&#x2B; Waterworks" name="Jill"/>
  <attendee name="Bill" company="Ace Movers" extra="yes"/>
</meeting>
図 392. XML データからの内部空白文字の除去
 // The following procedure returns a string that is the same
 // as the input string except that strings of whitespace are
 // converted to a single blank.
P rmvWhiteSpace   b
D rmvWhiteSpace   pi         65535a   varying
D   input                    65535a   varying const
D output          s                   like(input) inz('')

 * x'15'=newline  x'05'=tab     x'0D'=carriage-return
 * x'25'=linefeed x'40'=blank
D whitespaceChr   C                   x'15050D2540'
D c               s              1A
D i               s             10I 0
D inWhitespace    s               N   INZ(*OFF)
 /free
      // copy all non-whitespace characters to the return value
      for i = 1 to %len(input);
         c = %subst(input : i : 1);
         if %scan(c : whitespaceChr) &gt; 0;
            // If this is a new set of whitespace, add one blank
            if inWhitespace = *OFF;
               inWhitespace = *ON;
               output += ' ';
            endif;
         else;
            // Not handling whitespace now.  Add character to output
            inWhitespace = *OFF;
            output += c;
         endif;
      endfor;
      return output;
 /end-free
P rmvWhiteSpace   e

XML 命令について詳しくは、XML 命令を参照してください。