cniElementAsBitstream

获取指定元素的位流表示。与元素关联的解析器序列化元素及其所有子代。结果复制到调用者分配的内存。在指定的所有选项与原始位流的选项相 匹配的特殊情况下(例如,位流通过 MQInput 节点从 WebSphere MQ 队列读取,并且自从接收原始位流起消息未经任何修改),此原始位流会复制到用户所分配的内存中。在这种情况下,不要求解析器解析重新序列化的消息。

用于生成位流的算法取决于所用的解析器以及指定的选项。所有的解析器都支持下列方式:
  • 在 RootBitStream 方式下位流生成算法与输出节点所用的算法相同。 在此方式中,只有当所指向的元素位于具有相应结构的子树最前面时,才会获取有意义的结果。
  • 在 EmbeddedBitStream 方式下,不仅位流生成算法与输出节点所用的算法相同,而且以下内容还可通过与输出节点相同的方式来确定(如果未明确指定),这意味着,如果以下内容表示头,则可通过搜索 element 的先前兄弟来确定它们:
    • Encoding
    • CCSID
    • 消息集
    • 消息类型
    • 消息格式

    这样,确定这些属性的算法实质上与用于 ESQL BITSTREAM 函数的算法相同。

某些解析器还支持另一种方式 FolderBitStream,如果所指向的字段表示一个文件夹,则该方式会为任何子树生成有效的位流。

语法

CciSize cniElementAsBitstream(
    int*                returnCode,
    CciElement*                element,
    const struct CciByteArray* value,
    CciChar*                   messageType,
    CciChar*                   messageSet,
    CciChar*                   messageFormat,
    int                        encoding,
    int                        ccsid,
    int                        options);

参数

returnCode
来自函数(输出)的返回码。指定 NULL 指针表示节点不要处理错误。如果输入不是 NULL,则输出表示调用的成功状态。在执行此调用期间别的任何异常都重新抛出到流中的下一个上行节点。调用 cciGetLastExceptionData 获取有关异常的详细信息。
可能的返回码是:
  • CCI_SUCCESS
  • CCI_EXCEPTION
  • CCI_INV_ELEMENT_OBJECT
  • CCI_INV_DATA_POINTER
  • CCI_INV_DATA_BUFLEN
  • CCI_INV_BUFFER_TOO_SMALL
element
要序列化(输入)的语法元素。
要序列化(输入)的语法元素。必须是消息根的子代。
value
到 CciByteArray 结构的指针包含由调用者分配的到内存区域的指针,以及此内存(输出)的 CciBytes 大小。
messageType
消息类型定义用于从元素树(输入)创建位流。NULL 指针表示忽略此参数。同样,如果与元素关联的解析器对此值没有兴趣,例如,如果它是个一般 XML 解析器,则 忽略参数。
messageSet
消息集定义用于从元素树(输入)创建位流。NULL 指针表示忽略此参数。同样,如果与元素关联的解析器对此值没有兴趣,例如,如果它是个一般 XML 解析器 ,则同样忽略参数。
messageFormat
格式用于从元素树(输入)创建位流。NULL 指针表示忽略此参数。同样,如果与元素关联的解析器对此值没有兴趣,例如,如果它是个一般 XML 解析器,则 忽略参数。
encoding
编码在写位流(输入)时使用。此参数是必要的。您可以指定 0 值来表明应该使用的队列管理器编码。
ccsid
编写位流(输入)时要使用的编码字符集标识。此参数是必要的。您可以指定 0 值来表明应该使用的队列管理器的 ccsid。ccsid -1 表明使用 ccsid 信息来生成位流,该信息包含在由元素及其子代指向的字段组成的子树中。当前没有支持此选项的解析器。
options
指定应使用哪个位流生成方式的整型值。它可以采用以下某个值:
  • CCI_BITSTREAM_OPTIONS_ROOT
  • CCI_BITSTREAM_OPTIONS_EMBEDDED
  • CCI_BITSTREAM_OPTIONS_FOLDER

返回值

  • 如果成功,则返回保留位流所需内存的正确大小。
  • 如果调用者分配的内存不足,则 returnCode 设置为 CCI_BUFFER_TOO_SMALL。
  • 如果执行期间发生异常,则 returnCode 设置为 CCI_EXCEPTION。

示例

以下示例演示了应如何使用选项参数为消息树的不同部分生成位流。

此代码可以复制到样本 Transform 节点的 _evaluate 函数。对于如下所示的输入消息:
MQMD
RFH2
<test><data><stuff>things</stuff></data></test>
节点将传播 3 个消息,一个消息将输入消息的副本包含在 BLOB 域中。另一个消息将输入 RFH2 的副本作为消息体包含在 BLOB 域中。第三个消息将 <data></data> 文件夹作为消息体包含在 BLOB 域中。
CciMessage*          outMsg[3];
    CciTerminal* terminalObject;
  CciElement*          bodyChild;
  CciElement*          inRootElement;
  CciElement*          inSourceElement[3];
  CciElement*          outRootElement;
  CciElement*          outBlobElement;
  CciElement*          outBody;
  struct CciByteArray  bitstream[3];
  int                  bitstreamOptions[3];
  int                  retvalue;
    int                rc = 0;
  int                  loopCount;
  CCI_EXCEPTION_ST     exception_st = {CCI_EXCEPTION_ST_DEFAULT};
  const CciChar*       constBLOBParserName  =
                 cciString("NONE",BIP_DEF_COMP_CCSID);
  const CciChar*       constBLOBElementName = 
                 cciString("BLOB",BIP_DEF_COMP_CCSID);
  const CciChar*       constEmptyString     =                     
                 cciString("",BIP_DEF_COMP_CCSID);

  /*build up and propagate 3 output messages*/
  /*first message has bit stream for input message body*/
  /*second message has bit stream for input RFH2*/
  /*third message has bit stream for sub element from input message*/

  /* Get the root element of the input message */
  inRootElement = cniRootElement(&rc, message);
  /*CCI_CHECK_RC();*/
     checkRC(rc);

  /*set up the array of source elements and bitstream options*/

  /*message body*/
  inSourceElement[0] =  cniLastChild(&rc,inRootElement);
     checkRC(rc);

  /*This is the root of the message body so we use RootBitStream mode*/
  bitstreamOptions[0] = CCI_BITSTREAM_OPTIONS_ROOT;

  
  /*last header*/
  inSourceElement[1] = cniPreviousSibling(&rc,inSourceElement[0]);
     checkRC(rc);

  /*This is the root of the RFH2 so we use RootBitStream mode*/
  bitstreamOptions[1] = CCI_BITSTREAM_OPTIONS_ROOT;

  
  /*body.FIRST(first child of message body) */
  inSourceElement[2] = cniFirstChild(&rc,inSourceElement[0]);
     checkRC(rc);
  
  /*body.FIRST.FIRST */
  inSourceElement[2] = cniFirstChild(&rc,inSourceElement[2]);
     checkRC(rc);

  /*This is a sub tree within the message body so we use FolderBitStream mode*/
  bitstreamOptions[2] = CCI_BITSTREAM_OPTIONS_FOLDER;

  
  for (loopCount=0;loopCount<3;loopCount++) {
    int bufLength;

    /* Create new message for output */
    outMsg[loopCount] = cniCreateMessage(&rc, cniGetMessageContext(&rc, message));
       checkRC(rc);

    /* Get the root element of the output message */
    outRootElement = cniRootElement(&rc, outMsg[loopCount]);
       checkRC(rc);

    /* Copy the contents of the input message to the output message */
    cniCopyElementTree(&rc, inRootElement, outRootElement);
       checkRC(rc);

    /* Get the last child of root (ie the body)  */
    bodyChild = cniLastChild(&rc, outRootElement);
       checkRC(rc);

    /*throw away the message body which was copied from the input message*/
    cniDetach(&rc,
              bodyChild);
       checkRC(rc);

    /*create the new output message body in the BLOB domain*/
    outBody = cniCreateElementAsLastChildUsingParser(&rc,
                                                                                              outRootElement,
                                           constBLOBParserName);
       checkRC(rc);

    /*create the BLOB element*/
    outBlobElement = cniCreateElementAsLastChild(&rc,
                                outBody);
       checkRC(rc);

    cniSetElementName(&rc,
                      outBlobElement,
                      constBLOBElementName);
       checkRC(rc);
    
    /*Set the value of the blob element by obtaining the bit stream for the
    element */
    bitstream[loopCount].size=512;
    bitstream[loopCount].pointer=(CciByte*)malloc(sizeof(CciByte) * 512);
    
      bufLength = cniElementAsBitstream(&rc,
                          inSourceElement[loopCount],
                          &bitstream[loopCount],
                          constEmptyString,/*assume XML message so no interest in*/
                          constEmptyString,/* type, set or format*/
                          constEmptyString,
                          0,/*Use Queue Manager CCSID & Encoding*/
                                                         0,
                          bitstreamOptions[loopCount]);      
    

    if (rc==CCI_BUFFER_TOO_SMALL) {
free(bitstream[loopCount].pointer);
        bitstream[loopCount].size=bufLength;
        bitstream[loopCount].pointer=(CciByte*)malloc(sizeof(CciByte) * bitstream[loopCount].size);

          bufLength = cniElementAsBitstream(&rc,
                          inSourceElement[loopCount],
                          &bitstream[loopCount],
                          constEmptyString,/*assume XML message so no interest in*/
                          constEmptyString,/* type, set or format*/
                          constEmptyString,
                          0,/*Use Queue Manager CCSID & Encoding*/
                                                         0,
                          bitstreamOptions[loopCount]);      
    }
       checkRC(rc);
    bitstream[loopCount].size=bufLength;
    
    cniSetElementByteArrayValue(&rc,
                                outBlobElement,
                                &bitstream[loopCount]);
       checkRC(rc);
  }

  /* Get handle of output terminal */
  terminalObject = getOutputTerminalHandle( (NODE_CONTEXT_ST *)context,
                                            (CciChar*)constOut);

  /* If the terminal exists and is attached, propagate to it */
  if (terminalObject) {
        if (cniIsTerminalAttached(&rc, terminalObject)) {
      /* As this is a new, and changed message, it should be finalized... */
      cniFinalize(&rc, outMsg[0], CCI_FINALIZE_NONE);
      cniFinalize(&rc, outMsg[1], CCI_FINALIZE_NONE);
      cniFinalize(&rc, outMsg[2], CCI_FINALIZE_NONE);
      retvalue = cniPropagate(&rc, terminalObject, destinationList, exceptionList, outMsg[0]);
      retvalue = cniPropagate(&rc, terminalObject, destinationList, exceptionList, outMsg[1]);
      retvalue = cniPropagate(&rc, terminalObject, destinationList, exceptionList, outMsg[2]);
      if (retvalue == CCI_FAILURE) {
        		if (rc == CCI_EXCEPTION) {
          			/* Get details of the exception */
          memset(&exception_st, 0, sizeof(exception_st));
                    cciGetLastExceptionData(&rc, &exception_st);
          /* Any local error handling may go here */

          /* Ensure message is deleted prior to return/throw */
          cniDeleteMessage(0, outMsg[0]);
          cniDeleteMessage(0, outMsg[1]);
          cniDeleteMessage(0, outMsg[2]);

          /* We must "rethrow" the exception; note this does not return */
          			cciRethrowLastException(&rc);
        }
        else {

          /* Some other error...the plugin might choose to log it using the CciLog() */
          /* utility function                                                        */

        }
      }
      else {
      }
    }
  }
  else {
    /* Terminal did not exist...severe internal error. The plugin may wish to */
    /* log an error here using the cciLog() utility function.                 */
  }

  /* Delete the messages we created now we have finished with them */
  cniDeleteMessage(0, outMsg[0]);
  cniDeleteMessage(0, outMsg[1]);
  cniDeleteMessage(0, outMsg[2]);

  free((void*) constBLOBParserName);
  free((void*) constBLOBElementName);
  free((void*) constEmptyString);
  return;
声明 | 商标 | 下载 | 书库 | 支持 | 反馈
Copyright IBM Corporation 1999, 2006 最后一次更新时间:2006/08/14
as07885_