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

Re: Parsing XML with a value that contains a double quote



Hi Scott,

I've made the changes you suggested, and am now successfully writing the whole embedded xml to a temporary file in the IFS. But now when I parse it with http_parse_xml_stmf I get garbage in the "value" field of the "embedded" prototype, and sometimes that garbage contains the word EndElement. 

Here are code snippets---


     D resp_t          ds                  qualified
     D                                     based(Template)
     D transid                       50a   varying
     D respcode                      30a   varying
     D respcodetxt                   30a   varying      

     D embedded        PR
     D   resp                              likeds(resp_t)
     D   depth                       10I 0 value
     D   name                      1024A   varying const
     D   path                     24576A   varying const
     D   value                    32767A   varying const
     D   attrs                         *   dim(32767)
     D                                     const options(*varsize)    

       // ----------------------------------------------
        //    Parse the second XML document (the one
        //    that was embedded)
        // ----------------------------------------------
          resp = *allx'00';
          if (http_parse_xml_stmf( embfile
                                 : HTTP_XML_CALC
                                 : *null
                                 : %paddr(Embedded)
                                 : %addr(resp) ) < 0);
              unlink(embfile);
              http_crash();
          else;

            head = 1;
            exsr printRequest;

          endif;           


     P embedded        B
     D embedded        PI
     D   resp                              likeds(resp_t)
     D   depth                       10I 0 value
     D   name                      1024A   varying const
     D   path                     24576A   varying const
     D   value                    32767A   varying const
     D   attrs                         *   dim(32767)
     D                                     const options(*varsize)

     D Count           S             10I 0
     D attrname        s            100a   varying
     D attrval         s            100a   varying

      /free

         select;
         when name = 'TransactionID';
            resp.transid = %trimr(value);
         when name = 'ResponseCode';
            resp.respcode  = %trimr(value);
	   endsl;

	P                 E         


It's frustrating to me that I don't better understand this process. We simply don't have enough experience with API's and RPGLE. Yes, we're in serious need of modernization.

Any ideas??

Thanks so much,

Kim 



From: Kim Gibson 
Sent: Tuesday, December 28, 2010 8:25 AM
To: 'ftpapi@xxxxxxxxxxxxxxxxxxxxxx'
Subject: Re: Parsing XML with a value that contains a double quote

Ah, okay thanks. I had put the write into a loop because I thought perhaps I was going to have to retrieve the data in chunks when it exceeded 65535. I'll give this a shot and see if retval.valptr contains the whole huge embedded xml data.

You're right about the XML header-doh.

I'll give this a try this morning. Thanks!

Kim

Date: Mon, 27 Dec 2010 18:13:16 -0600
From: Scott Klement <sk@xxxxxxxxxxxxxxxx>
Subject: Re: Parsing XML with a value that contains a double quote
To: HTTPAPI and FTPAPI Projects <ftpapi@xxxxxxxxxxxxxxxxxxxxxx>
Message-ID: <4D192B9C.8090707@xxxxxxxxxxxxxxxx>
Content-Type: text/plain; charset=ISO-8859-1; format=flowed

Hi Kim,

I wouldn't use the 'WriteToFile' prototype you presented.  Instead, I'd 
use the 'standard' write prototype...  i.e. the one included in the 
IFSIO_H member that's part of HTTPAPI.

Then I'd just do this:

    fd = open(embfile: O_CREAT+O_WRONLY+O_TEXTDATA);
    callp write(fd: retval.valptr: retval.len);
    callp close(fd);

There's no need to write an XML header if you're parsing it with Expat. 
(It should already know that the data is XML)  There's also no need to 
call it in a loop, you should have the whole XML document already in 
retval.valptr (unless I'm mistaken?)

The only thing you might consider is translating the data back to ASCII 
when you write it (because HTTPAPI has translated it to EBCDIC for you.)

    fd = open( embfile
             : O_CREAT + O_WRONLY + O_EXCL +
               O_CCSID + O_TEXTDATA + O_TEXT_CREAT
             : S_IRUSR + S_IWUSR
             : 819
             : 0 );
    callp write(fd: retval.valptr: retval.len);
    callp close(fd);

That code should cause the open() API to automatically translate the 
data to iso-8859-1 (CCSID 819) when it writes the data to disk.  That 
makes it easier when you want to open the file with Notepad or a browser 
(for debugging) and means that Expat has to jump through fewer hoops 
(since it doesn't understand EBCDIC directly, but does understand ASCII.)


On 12/27/2010 5:43 PM, Kim Gibson wrote:
>
>     Hello again,
>
>
>     I'm using a pointer to read the large amount of data being returned in
>     the http_url_post_xml response. I know how to use a pointer to read
>     data coming in from a file in the IFS, but what about data that simply
>     resides in memory? I'm sure I'm just missing something very elementary
>     here.
>
>
>     Here are relevant snippets of my code:
>
>
>     I've got a data structure that contains a pointer and a length:
>
>
>          D value_t         ds                  qualified
>
>          D   valptr                        *
>
>          D   len                         10i 0
>
>
>     I've altered my EndOfElement prototype definition to include the data
>     structure:
>
>
>          D EndOfElement    PR
>
>          D   UserData                      *   value
>
>          D   depth                       10I 0 value
>
>          D   name                      1024A   varying const
>
>          D   path                     24576A   varying const
>
>          D   retval                            likeds(value_t)
>
>          D   attrs                         *   dim(32767)
>
>          D                                     const options(*varsize)
>
>
>
>     I'm using http_XmlReturnPtr:
>
>
>       http_XmlReturnPtr(*ON);
>
>
>
>     My call to the web service looks like this:
>
>
>           rc = http_url_post_xml(
>
>               'https://someurl.com/services/eoservice.asmx'
>
>                     : %addr(SOAP)+2
>
>                     : %len(SOAP)
>
>                     : %paddr(StartOfElement)
>
>                     : %paddr(EndOfElement)
>
>                     : *NULL );
>
>
>
>
>     The return tag "DeliverExamOneContentResult" contains all the
>     unescaped data that I want to write to a temporary file in the IFS, so
>     I can read it back in and parse it with http_parse_xml_stmf.
>
>
>          P EndOfElement    B
>
>          D EndOfElement    PI
>
>          D   UserData                      *   value
>
>          D   depth                       10I 0 value
>
>          D   name                      1024A   varying const
>
>          D   path                     24576A   varying const
>
>          D   retval                            likeds(value_t)
>
>          D   attrs                         *   dim(32767)
>
>          D                                     const options(*varsize)
>
>
>          D writeToFile     PR            10I 0 ExtProc('write')
>
>          D  fildes                       10i 0 value
>
>          D  buf                       65535A   const options(*varsize)
>
>          D  bytes                        10U 0 value
>
>
>          D xmlhdr          s             80a   varying
>
>          D fd              s             10i 0
>
>
>           /free
>
>
>                if (%trim(name)<>  'DeliverExamOneContentResult');
>
>                  return;
>
>                endif;
>
>
>                // ------------------------------------------
>
>                //   create new stream file in IFS
>
>                // ------------------------------------------
>
>
>                embfile = http_tempfile();
>
>
>                // ------------------------------------------
>
>                //    Open stream file for appending data
>
>                //    and write embedded XML document to it
>
>                // ------------------------------------------
>
>
>                fd = open(embfile: O_WRONLY+O_TEXTDATA);
>
>
>                xmlhdr= '<?xml version="1.0"?>' + x'0d25';
>
>                writeToFile(fd: xmlhdr: %len(xmlhdr));
>
>
>          // here's where the problem is - how to I retrieve the data from
>     memory?
>
>          // Whenever I use %addr(retval.valptr), I get a compile error:
>
>          // The type of the parameter specified for the call does not
>     match the prototype.
>
>
>                dow writeToFile(fd: %addr(retval.valptr) : retval.len)>=0;
>
>                  writeToFile(fd: %addr(retval.valptr) : retval.len);
>
>                enddo;
>
>
>                callp close(fd);
>
>
>
>             //endsl;
>
>
>           /end-free
>
>          P                 E
>
>
>     I see that retval.valptr is a pointer and parameter buf in writeToFile
>     is a character field---how do I return the data at pointer
>     retval.valptr? What am I missing?
>
>
>     Thanks for your help--again!
>
>
>     Kim Gibson


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