ASG
IBM
Zystems
Cressida
Icon
Netflexity
 
  MQSeries.net
Search  Search       Tech Exchange      Education      Certifications      Library      Info Center      SupportPacs      LinkedIn  Search  Search                                                                   FAQ  FAQ   Usergroups  Usergroups
 
Register  ::  Log in Log in to check your private messages
 
RSS Feed - WebSphere MQ Support RSS Feed - Message Broker Support

MQSeries.net Forum Index » WebSphere Message Broker (ACE) Support » Message Tree from [XML] String

Post new topic  Reply to topic
 Message Tree from [XML] String « View previous topic :: View next topic » 
Author Message
goffinf
PostPosted: Thu Apr 05, 2007 10:05 am    Post subject: Message Tree from [XML] String Reply with quote

Chevalier

Joined: 05 Nov 2005
Posts: 401

I have an inbound message in which an XML fragment has been stored as a Base64 encoded value (its used for passing state between endpoints). It looks a bit like this :-

<Message>
<metaData>
<RequestorSavedState>
<SavedState>PE1CU2VydmljZVN0YXRlPjx .....</SavedState>
</RequestorSavedState>
</metaData>
<payload>foo</payload>
</Message>

Converting the SavedState element content back into its XML [string] representation is obviously easy enough, but is there a way that I can create part of my output message tree structure from this string (other than through crufty string manipulation). The structure is element normal form only (so no attributes to worry about) and there are no namespaces either.

Thanks

Fraser.
Back to top
View user's profile Send private message
jefflowrey
PostPosted: Thu Apr 05, 2007 10:06 am    Post subject: Reply with quote

Grand Poobah

Joined: 16 Oct 2002
Posts: 19981

Create Field... PARSE
_________________
I am *not* the model of the modern major general.
Back to top
View user's profile Send private message
kimbert
PostPosted: Thu Apr 05, 2007 11:58 am    Post subject: Reply with quote

Jedi Council

Joined: 29 Jul 2003
Posts: 5542
Location: Southampton

Jeff is correct. CREATE...PARSE will do the job. The base64 encoding introduces a small complication, though. You cannot parse a base64 character stream using an XML parser. Your options are:
- Use a Java Compute Node to decode the base64.
- Wrap the base64 stuff in a simple XML element and parse it using the MRM XML parser, and using a message set which defines the element's 'Encoding' as base64.

If it was me, I'd go for the first option.
Back to top
View user's profile Send private message
marcin.kasinski
PostPosted: Thu Apr 05, 2007 12:05 pm    Post subject: Reply with quote

Sentinel

Joined: 21 Dec 2004
Posts: 850
Location: Poland / Warsaw

kimbert wrote:
- Use a Java Compute Node to decode the base64.


Broker can help you with it.

Use com.ibm.broker.javacompute.Base64 class to do it.
_________________
Marcin
Back to top
View user's profile Send private message Visit poster's website
jefflowrey
PostPosted: Thu Apr 05, 2007 12:16 pm    Post subject: Reply with quote

Grand Poobah

Joined: 16 Oct 2002
Posts: 19981

marcin.kasinski wrote:
kimbert wrote:
- Use a Java Compute Node to decode the base64.


Broker can help you with it.

Use com.ibm.broker.javacompute.Base64 class to do it.



CREATE PROCEDURE b64Encode(IN source BLOB)
RETURNS CHARACTER
LANGUAGE JAVA
EXTERNAL NAME "com.ibm.broker.javacompute.Base64.encode";

similarly for decode.
_________________
I am *not* the model of the modern major general.
Back to top
View user's profile Send private message
goffinf
PostPosted: Fri Apr 06, 2007 7:15 am    Post subject: Reply with quote

Chevalier

Joined: 05 Nov 2005
Posts: 401

jefflowrey wrote:
Create Field... PARSE


OK. but now I'm a bit confused.

According to the prototype for the CREATE function, the PARSE clause takes a bitstream expression as its first argument, so does that mean I need to decode from Base64 into CHAR and then convert this result to a BITSTREAM ??. The of course the ASBITSTREAM function requires a field reference as its first argument ??

I'm sure you guys know this stuff better than I do, but I just want to emphasis that the content of the SavedState node is CHAR data that just happens to be the string representation of an XML structure, but its is not actually *in* that structure in the message tree at that point (thats what I'm trying to create from it) :-

I also note that the ESQL reference states that the DOMAIN clause must not be used with CREATE if you also use PARSE (I guess that will be OK since the parser I am using is XMLNSC).

I tried this (a bit long hand but using a bunch of variables so I can see which steps work or not) but it didn't work. Am I way off track here ? :-


SET OutputRoot.XMLNSC.Message = InputRoot.XMLNSC.Message;

-- extract the savedState

DECLARE afheadersAsBase64 CHARACTER;
DECLARE afheadersAsString CHARACTER;
DECLARE afheadersAsBLOB BLOB;
DECLARE afheadersTemp REFERENCE TO InputRoot.XMLNSC;

SET afheadersAsBase64 = OutputRoot.XMLNSC.Message.metaData.RequestorSavedState.SavedState;

-- Decode from Base64 (this is our own eSQL function and works fine)
-- put it in a variable for now just to check
SET afheadersAsString = B64Decode(afheadersAsBase64);

-- Set the decoded value into the SavedState location
SET OutputRoot.XMLNSC.Message.metaData.RequestorSavedState.SavedState = afheadersAsString;

-- Everything's OK so far

-- String to BITSTREAM
DECLARE savedStateRef REFERENCE TO OutputRoot.XMLNSC.Message.metaData.RequestorSavedState.SavedState;
DECLARE savedStateAsBLOB BLOB ASBITSTREAM(savedStateRef, InputProperties.Encoding,InputProperties.CodedCharSetId,'','','',FolderBitStream);

-- savedStateRef DOES REFERENCE THE CHARACTER DATA WHICH IS THE XML STRING

-- BUT savedStateAsBLOB CONTAINS NO DATA AT ALL


-- Create an XML message tree fragment from the string
CREATE FIELD Environment.XMLNSC.afheadersTemp AS afheadersTemp;

-- THE NEXT LINE THROWS AN EXCEPTION (PRESUMABLY SINCE savedStateAsBLOB IS EMPTY)

CREATE FIRSTCHILD OF afheadersTemp AS afheadersTemp DOMAIN('XMLNSC') PARSE(savedStateAsBLOB, InputProperties.Encoding, InputProperties.CodedCharSetId);

Cheers

Fraser.
Back to top
View user's profile Send private message
goffinf
PostPosted: Fri Apr 06, 2007 10:25 am    Post subject: Reply with quote

Chevalier

Joined: 05 Nov 2005
Posts: 401

jefflowrey wrote:
marcin.kasinski wrote:
kimbert wrote:
- Use a Java Compute Node to decode the base64.


Broker can help you with it.

Use com.ibm.broker.javacompute.Base64 class to do it.



CREATE PROCEDURE b64Encode(IN source BLOB)
RETURNS CHARACTER
LANGUAGE JAVA
EXTERNAL NAME "com.ibm.broker.javacompute.Base64.encode";

similarly for decode.


Cool. Sorry for being a bit thick, but can I use the eSQL just as you have it here, that is, do I actually need a javacompute node in my flow.
Back to top
View user's profile Send private message
marcin.kasinski
PostPosted: Fri Apr 06, 2007 12:08 pm    Post subject: Reply with quote

Sentinel

Joined: 21 Dec 2004
Posts: 850
Location: Poland / Warsaw

goffinf wrote:

Sorry for being a bit thick, but can I use the eSQL just as you have it here, that is,


Yes you can.


goffinf wrote:


do I actually need a javacompute node in my flow.


You don't need this node in your flow.


Just try this ESQL code.
_________________
Marcin
Back to top
View user's profile Send private message Visit poster's website
kimbert
PostPosted: Fri Apr 06, 2007 12:33 pm    Post subject: Reply with quote

Jedi Council

Joined: 29 Jul 2003
Posts: 5542
Location: Southampton

hi gofinf,

You're mostly doing the right things, but the details matter ( as you've found out). Hopefully this will help...

Quote:
does that mean I need to decode from Base64 into CHAR
Yes
Quote:
and then convert this result to a BITSTREAM
The input to CREATE...PARSE is a BLOB, so you need to CAST the resulting CHARACTER data to a BLOB.

Quote:
The of course the ASBITSTREAM function requires a field reference as its first argument ??
Correct. What's strange about that? ASBITSTREAM does the exact opposite of CREATE...PARSE. It creates a BLOB from a message tree.

Quote:
I also note that the ESQL reference states that the DOMAIN clause must not be used with CREATE if you also use PARSE
Where does it say that? You must use the domain clause when you use CREATE...PARSE. How else will WMB know which parser to use?

Quote:
it didn't work. Am I way off track here ?

Not too far off track. I would do it this way:

- Decode the base64 date to a CHARACTER field
- CAST the character field to a BLOB
- CREATE LASTCHILD OF <somwhere> DOMAIN "XMLNSC" PARSE <the BLOB> CCSID <from input message> ENCODING <from input message>

You don't need to use ASBITSTREAM anywhere. All you need is a BLOB, and you can get that using CAST.

By the way, re:
Code:
-- Create an XML message tree fragment from the string
CREATE FIELD Environment.XMLNSC.afheadersTemp AS afheadersTemp;
...I hope that Environment.XMLNSC was created using the Domain clause.
Back to top
View user's profile Send private message
goffinf
PostPosted: Mon Apr 09, 2007 9:16 am    Post subject: Reply with quote

Chevalier

Joined: 05 Nov 2005
Posts: 401

kimbert wrote:
You're mostly doing the right things, but the details matter ( as you've found out). Hopefully this will help...


Thanks, it helped a lot.

goffinf wrote:
I also note that the ESQL reference states that the DOMAIN clause must not be used with CREATE if you also use PARSE
[quote="kimbert]Where does it say that? You must use the domain clause when you use CREATE...PARSE. How else will WMB know which parser to use?[/quote]

The 'Notes' under the railroad diagram for the CREATE statement say :-

Notes:
1. Do not use the DomainClause and ParseClause with the FIELD qualifier.

But it didn't matter because I didn't use CREATE FIELD anyway, as per your advice

kimbert wrote:
I would do it this way:

- Decode the base64 date to a CHARACTER field
- CAST the character field to a BLOB
- CREATE LASTCHILD OF <somwhere> DOMAIN "XMLNSC" PARSE <the BLOB> CCSID <from input message> ENCODING <from input message>


Thanks that worked OK. I did (and possibly still do) have one problem though. When the message comes into my flow there is no value for either the encoding or CCSID (these flows use a custom input node so I wasn't surprised). Passing these empty values causes the CREATE LASTCHILD to exception, so I ended up having to hard code in 1208 for CCSID (we are only using XML and using UTF-8 encoding) and 546 for the ENCODING value. Is this going to be a problem when I deploy this flow onto a non Windows platform ?? Is there a better approach ??

kimbert wrote:
By the way, re:
Code:
-- Create an XML message tree fragment from the string
CREATE FIELD Environment.XMLNSC.afheadersTemp AS afheadersTemp;
...I hope that Environment.XMLNSC was created using the Domain clause.


Yeh sorry I didn't explain that bit. It Environment.XMLNSC is what we internally call our XML 'scratch-pad' and it *is* created using the XMLNSC Domain.

Regards

Fraser.
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic  Reply to topic Page 1 of 1

MQSeries.net Forum Index » WebSphere Message Broker (ACE) Support » Message Tree from [XML] String
Jump to:  



You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
Protected by Anti-Spam ACP
 
 


Theme by Dustin Baccetti
Powered by phpBB © 2001, 2002 phpBB Group

Copyright © MQSeries.net. All rights reserved.