[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RE: Advice on how to process xsd:base64Binary XML element retrieved from a web service.



You look to be on the right path. I am not sure why you are having problems with count and transactionIdOut. To get started, just define them as character fields. Does that work?

Good. Now you just need to convert to numbers.

Monitor;
  Count = %dec(%trim(countChar):5:0); // should work - probably shouldn't need the %trim but never hurts
On-error;
  Dsply countChar;
End-mon;

As for resultVar. Write it to the IFS. The prototypes for writing to the IFS are already included in HTTPAPI so you can use them to do the lifting. If you haven't written to the IFS, this article is one of the short and sweet versions. http://iprodeveloper.com/rpg-programming/writing-delimited-file-ifs-hard-way Actually, maybe EXAMPLE17 is even easier. See SaveEmbed procedure.

Once written to the IFS, HTTPAPI with Expat can be used to parse the stream file. See http_parse_xml_stmf

 


-----Original Message-----
From: ftpapi-bounces@xxxxxxxxxxxxxxxxxxxxxx [mailto:ftpapi-bounces@xxxxxxxxxxxxxxxxxxxxxx] On Behalf Of PReid@xxxxxxxxxxxx
Sent: Monday, December 16, 2013 3:33 PM
To: HTTPAPI and FTPAPI Projects
Subject: Re: Advice on how to process xsd:base64Binary XML element retrieved from a web service.

Hello again.

I feel like I'm getting closer with this, but I'm still not there. Just to 
refresh your memory the Response XML that I get back looks like this:

 <soapenv:Body>
   <dequeue2Response>
      <dequeue2Return>
         <count>6</count>
 <transactions>PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz...=</transactions>
         <transactionIdOut>58744654</transactionIdOut>
      </dequeue2Return>
   </dequeue2Response>
</soapenv:Body>

I implemented the code that Scott recommended into my program, and I think 
it is working, I just have a few questions. 

#1. I could not define the "resultVar" variable as it was shown below 
(without a Variable Type). I kept getting the following errors:
 NF3391E The LEN keyword is valid only for Data Structures, or for type A, 
C, or G; keyword is ignored.
 RNF3365E Keyword VARYING is allowed only for an item defined as 
character, graphic, or UCS-2.
 RNF3438E LIKE keyword is expected for field RESULTVAR but not found; 
definition is ignored.
I defined it as Variable Type "C" which i believe means UCS-2...but I'm 
not sure if this is correct. It might depend on question #2 below.
 
#2. The "transactions" element is base64 encoded and I believe that the 
example code that Scott showed me is in fact decoding it...I am just at a 
loss as to what to do with it. The data that is encoded in the element, is 
itself,  an XML document. I am thinking that I should write this out to a 
temporary file on the IFS and then parse it later in the program?,..but I 
don't know how to output an XML to the IFS?...I'm also not sure if this is 
the best way to handle this situation...In the end I want to write this 
data into files on our IBMi. 
 
#3. The "count" and "transactionIdOut" elements are not base64 encoded, 
however; I do need the data returned in these fields. With the changes 
that I've made to my "Incoming" procedure, I can't seem to retrieve the 
data stored in the "value" field. How do I get these values out of the new 
"value" data structure?

Below I am including...what I think...is the relevant portions of code 
from my program. I can supply the entire program if you want. 
*
*------------------------------------------------------------------------*
*
D Incoming        PR
D   rate                         8F
D   depth                       10I 0 value
D   name                      1024A   varying const
D   path                     24576A   varying const
D   value                             likeds(Xmlstring_t)
D   attrs                         *   dim(32767)
D                                     const options(*varsize)
*
* Log.
D dequeue2...
D                 S           1000A   varying
*
* Can't figure out how to get the data into these fields.
D count...
D                 S              5P 0 inz(*zeros)
D transactionIdOut...
D                 S             17P 0 inz(*zeros)
*
* Not sure if resultVar is defined correctly?
D resultVar       S               C    len(2000000) varying
D decodedLen      S             10I 0
*
*------------------------------------------------------------------------*
*
// Write out a Log.
   dequeue2 = '/home/PAULRE/dequeue2.txt';
   http_debug(*ON : dequeue2);

// Change the way the XML parser returns the data.
// We need to use pointer since it is so large...
   http_XmlReturnPtr(*on);

// Post.
   rc = http_url_post_xml(
       'https://www.myshawtracking.ca:443/otsWebWS/services/OTSWebSvcs'
      : %addr(SOAP) + 2
      : %len(SOAP)
      : *NULL
      : %paddr(Incoming)
      : %addr(rate)
      : HTTP_TIMEOUT
      : HTTP_USERAGENT
      : 'text/xml'
      : 'http://www.qualcomm.com/dequeue2');

// Success!!!
   if rc = 1;
*
*------------------------------------------------------------------------*
*
P Incoming        B
*
D Incoming        PI
D   rate                         8F
D   depth                       10I 0 value
D   name                      1024A   varying const
D   path                     24576A   varying const
D   value                             likeds(XmlString_t)
D   attrs                         *   dim(32767)
D                                     const options(*varsize)
*
/free

    // This value is not base64 encoded.
    // I can't figure out how to get data into this field.
    if name = 'count';
       // count = %dec(value:5:0);

    // This value is base 64 encoded, I think this is working, and the 
data is 
    // in resultVar...now what do I do with it?
    elseif name = 'transactions';
       %len(resultVar) = %len(resultVar : *MAX);
       decodedLen = base64_decode( value.data
                                 : value.len
                                 : %addr(resultVar : *data)
                                 : %len(resultVar : *MAX) );
       %len(resultVar) = decodedLen;

    // This value is not base64 encoded - not sure how to retrieve it?
    // I can't figure out how to get data into this field.
    elseif name = 'transactionIdOut';
       // transactionIdOut = %dec(value:17:0);

    endif;

/end-free
*
P Incoming        E


Thanks very much for your time. If there is any more information you need, 
just let me know.
Have a great day!
___________________________________________________________
Paul Reid
Application Developer III
Erb Group of Companies | 290 Hamilton Road | New Hamburg, Ontario | N3A 
1A2
Phone: 519.662.6133 ext. 2363
Web: http://www.erbgroup.com/



From:   Scott Klement <sk@xxxxxxxxxxxxxxxx>
To:     HTTPAPI and FTPAPI Projects <ftpapi@xxxxxxxxxxxxxxxxxxxxxx>
Date:   12/13/2013 12:56 AM
Subject:        Re: Advice on how to process xsd:base64Binary XML element 
retrieved       from a web service.
Sent by:        ftpapi-bounces@xxxxxxxxxxxxxxxxxxxxxx



hi Paul,

HTTPAPI was originally written for OS/400 V4R2, and therefore does not 
"directly" support variables longer than 65535 characters long. However, 
in many cases HTTPAPI does have pointer-based interfaces that allow data 
as large as 16 MB to be returned -- so in order to handle data "up to 
approx 1 MB" you will want to use the pointer-based interfaces.  You can 
use them in conjunction with V7R1's support for large variables.

Steps:
1) Before calling http_url_post_xml(), you should call 
http_XmlReturnPtr(*ON).  What this does is change the way the XML parser 
returns data.  Instead of returning as a 65535 character string, it will 
now return it as a data structure, that has subfield for a pointer, and 
a subfield with a 10i 0 integer containing the length of the string in 
bytes.

D XmlString_t     ds                  qualified Template
D   Data                          *
D   Len                         10i 0

2) Change your 'Incoming' procedure (NOTE: you can call this procedure 
whatever you like, it does not have to be 'Incoming', that was just a 
name I used as an example) to receive this data structure in place of 
the 'value' string.

D Incoming        PR
D   rate 8F
D   depth                       10I 0 value
D   name                      1024A   varying const
D   path                     24576A   varying const
D   value likeds(XmlString_t)
D   attrs                         * dim(32767)
D                                     const options(*varsize)

3) Now that 'value' is coming in as a pointer, it can be as large as you 
want.  You can now pass the 'value' parameter to tbe base64_decode 
procedure to eliminate the base64 encoding. Personally I like to use a 
VARYING variable for this sort of thing, and there's a trick to working 
with VARYING as a pointer...   you need to set it's length to the 
maximum length first, then pass the address of only the data portion, 
then set it's length back to the returned length.

D resultVar       s                   len(2000000) varying

      %len(resultVar) = %len(resultVar: *MAX);

      decodedlen = base64_decode( value.data
                                : value.len
                                : %addr(resultVar: *data)
                                : %len(ResultVar: *MAX) );

      %len(resultVar) = decodedlen;

4) Now you have the decoded data in 'resultVar'.  However, you should 
know that this data will have the exact same binary value that it had 
when it was encoded.  If your data is text and the sender had it encoded 
in ASCII (or Unicode), then your data in resultVar will in ASCII, so 
you'll probably want to translate it to EBCDIC next.

If the data in resultVar is not text, like an image, PDF, Word Document, 
sound file, etc...  then you won't want to translate it to EBCDIC, as 
that would corrupt the data.  (That is what is meant by 'binary')

5) Not sure what you want to do next, it'll depend on the purpose of 
this data.  Should it be written to the IFS?  Stored in a BLOB?  So I'll 
leave that part as an exercise for you.

Good luck....



On 12/12/2013 9:48 AM, PReid@xxxxxxxxxxxx wrote:
>     Hello everyone. I am not very experienced with Web Services so bear
>     with me. I did a fair bit of research on the various forums before
>     posting, but I failed to find a good example of what I am looking 
for.
>     I'm hoping that someone can help, possibly with an example.
>     I am predominately an RPG programmer. We are running an IBM Power 7 
at
>     V7R1, and I have Scott's HTTPAPI V1.24 downloaded and installed. I 
am
>     using HTTPAPI to consume another Web Service and it works 
beautifully.
>     My latest challenge it that I have consume a Web Service that 
includes
>     an element in the XML response that is data type xsd:base64Binary 
and
>     I'm not really sure how to do it. The WSDL for this web service is:
>     [1]
https://www.myshawtracking.ca/otsWebWS/services/OTSWebSvcs/wsdl/OTSW
>     ebSvcs.wsdl
>     The WIKI for this Web Service is:
>     [2]
https://intinfo.myqualcomm.com/display/iWebInt/ESS+High-Volume+Deque
>     ue
>     The method that I must consume is named DEQUEUE2.
>     I have created an RPG program that POSTS a request to the Web 
Service
>     using the following HTTPAPI subprocedure:
>        rc = http_url_post_xml(
>
>     'https://www.myshawtracking.ca:443/otsWebWS/services/OTSWebSvcs'
>                  : %addr(SOAP) + 2
>                  : %len(SOAP)
>                  : *NULL
>                  : %paddr(Incoming)
>                  : %addr(rate)
>                  : HTTP_TIMEOUT
>                  : HTTP_USERAGENT
>                  : 'text/xml'
>                  : 'http://www.qualcomm.com/dequeue2');
>     I am receiving rc = 1 which I believe means that I am successfully
>     receiving an XML response. FYI - The procedure "Incoming" was copied
>     from Scott's EXAMPLE11.
>     The response XML is as follows.
>     <soapenv:Body>
>     <dequeue2Response>
>     <dequeue2Return>
>     <count>6</count>
>     <transactionIdOut>58744654</transactionIdOut>
>     (transactions>
>     PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48dHJjaz4=
>     </transactions>
>     </dequeue2Return>
>     </dequeue2Response>
>     </soapenv:Body>
>     The "transactions" element is xsd:base64Binary and I don't know how 
to
>     decode it. I have downloaded Scott's BASE64R4 service program and I
>     suspect I'd use procedure BASE64_DECODE, but I'm not sure how I 
would
>     employ it in this situation. Also...according to the wiki the
>     "transactions" element could be as large as "Approximately  1mb"
>     although I'm not really sure what they mean by approximately??
>     The "count" and "transactionIdOut" and not encoded and I need the 
data
>     in them in addition to the encoded data.
>     I understand that I may not even be using the correct post procedure
>     (remember I'm not that experienced) and in the interim I am going to
>     try some of Scott's other procedures.
>     Any help or examples on how to get this data would be much 
appreciated.
>     Thanks!
>     ___________________________________________________________
>     Paul Reid
>     Application Developer III
>     Erb Group of Companies | 290 Hamilton Road | New Hamburg, Ontario | 
N3A
>     1A2
>     Phone: 519.662.6133 ext. 2363
>     Web: [3]http://www.erbgroup.com/
>
> References
>
>     1. 
https://www.myshawtracking.ca/otsWebWS/services/OTSWebSvcs/wsdl/OTSWebSvcs.wsdl

>     2. 
https://intinfo.myqualcomm.com/display/iWebInt/ESS+High-Volume+Dequeue
>     3. http://www.erbgroup.com/
>
>
>
> -----------------------------------------------------------------------
> This is the FTPAPI mailing list.  To unsubscribe, please go to:
> http://www.scottklement.com/mailman/listinfo/ftpapi
> -----------------------------------------------------------------------

-----------------------------------------------------------------------
This is the FTPAPI mailing list.  To unsubscribe, please go to:
http://www.scottklement.com/mailman/listinfo/ftpapi
-----------------------------------------------------------------------

-----------------------------------------------------------------------
This is the FTPAPI mailing list.  To unsubscribe, please go to:
http://www.scottklement.com/mailman/listinfo/ftpapi
-----------------------------------------------------------------------