Use this function to get the bitstream representation of the specified element.
The parser that is associated with the element serializes the element and all its child elements. 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 reserialize 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 you can use the options parameter to generate the bit stream for different parts of the message tree.
MQMD
MQRFH2
<test><data><aaa>text</aaa></data></test>
the node propagates three messages: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 can 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 might want to */
/* log an error here by 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;