Gets the bitstream representation of the specified element. The parser that is associated with the element serializes the element and all its children. The result is copied to memory allocated by the caller. In the special case where all the options that are specified match those of the original bit stream, for example a bit stream that is read from a WebSphere MQ queue by the MQInput node, and the message has not been modified since receiving the original bit stream, this original bit stream is copied into the allocated memory. In this case, the parser is not required to parse and re-serialize the message.
In this way, the algorithm for determining these properties is essentially the same as that used for the ESQL BITSTREAM function.
Some parsers also support another mode, FolderBitStream, which generates a meaningful bit stream for any subtree, provided that the field pointed to represents a folder.
CciSize cniElementAsBitstream( int* returnCode, CciElement* element, const struct CciByteArray* value, CciChar* messageType, CciChar* messageSet, CciChar* messageFormat, int encoding, int ccsid, int options);
The following example demonstrates how the options parameter can be used to generate the bit stream for different parts of the message tree.
MQMD MQRFH2 <test><data><foo>text</foo></data></test>the node propagates three messages; one that contains a copy of the input message in the BLOB domain, one that contains a copy of the input MQRFH2 as the message body in the BLOB domain, and one that contains the <data></data> folder as the message body in the BLOB domain.
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 MQRFH2*/ /*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 MQRFH2 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, localEnvironment, exceptionList, outMsg[0]); retvalue = cniPropagate(&rc, terminalObject, localEnvironment, exceptionList, outMsg[1]); retvalue = cniPropagate(&rc, terminalObject, localEnvironment, 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;