Application Development and Automation Discussions
Join the discussions or start your own on all things application development, including tools and APIs, programming models, and keeping your skills sharp.
cancel
Showing results for 
Search instead for 
Did you mean: 
Read only

Internal table to XML data in Application Server

Brunot
Explorer
0 Likes
2,022

Hi, i am struggling with transferring a xml file onto application server.

MY release is 46c.

When using open-transfer-close to transfer the generated xml from an internal table,the very last record contains junk characters

(is the closing tag) (I.E. </p:FatturaElettronica>############################## ).

This issue is urgent as i cannot send the invoice xml file to client.

I hope someone can help.

Thanks.

Here is my code:

DATA: lr_stream_factory    TYPE REF TO if_ixml_stream_factory,
    lr_ostream           TYPE REF TO if_ixml_ostream,
    lr_ostream_string    TYPE REF TO if_ixml_ostream,
    lr_ostream_xstring    TYPE REF TO if_ixml_ostream.

  DATA: lt_xml        TYPE ckf_t_xml,
    ld_size       TYPE i,
    lt_xml_stru   TYPE LINE OF ckf_t_xml.

  DATA: lr_renderer   TYPE REF TO if_ixml_renderer,
    ld_rc         TYPE i.                       "#EC NEEDED

  DATA xstring_xml TYPE xstring.

  DATA string_xml TYPE string.

* create stream factory

  lr_stream_factory = pr_ixml_factory->create_stream_factory( ).

* create output stream

  lr_ostream =

lr_stream_factory->create_ostream_itable( table = lt_xml ).

* create renderer

  lr_renderer = pr_ixml_factory->create_renderer(

    ostream  = lr_ostream

    document = pr_dom ).

set render modus

  DATA: ld_bool TYPE boolean.                               "#EC NEEDED

  ld_bool = lr_renderer->set_normalizing( ).

* render dom into xml

  ld_rc = lr_renderer->render( ).

* download to pc

  ld_size = lr_ostream->get_num_written_raw( ).

  OPEN DATASET pr_filename FOR OUTPUT IN BINARY MODE.

*--- Display error messages if any.

  IF sy-subrc NE 0.

    MESSAGE e038(zsd) WITH 'Errore apertura file'.

    EXIT.

  ELSE.

*---Data is downloaded to the application server file path

    LOOP AT lt_xml INTO lt_xml_stru.

      TRANSFER lt_xml_stru TO pr_filename.

    ENDLOOP.

  ENDIF.

*--Close the Application server file (Mandatory).

  CLOSE DATASET pr_filename.

1 ACCEPTED SOLUTION
Read only

bernardo_lee
Explorer
0 Likes
1,269

Hi Bruno,

Maybe you can use a different approach. Try to creat your xml fila as text and then convert it to xml.

The code would be something like this:

data: ixml                   type ref to if_ixml,
         xml_document  type ref to if_ixml_document.
     
data: lv_string   type string,
      lv_xstring  type xstring.

* Create the header
lv_string = '<Header>'.

* Attach data from the internal table
loop at i_table.
    concatenate lv_string i_table-field into lv_string.
     " add elements as needed

endloop.

* Attach the footer
concatenate lv_string '</Header>' into lv_string.

* Convert string to xstring
lv_xstring = cl_proxy_service=>cstring2xstring( lv_string ).

*create ixml dom document from xml xstring
        call function 'SDIXML_XML_TO_DOM'
          exporting
            xml           = lv_xstring
          importing
            document      = xml_document
          exceptions
            invalid_input = 1
            others        = 2.

Bernardo

6 REPLIES 6
Read only

Former Member
0 Likes
1,269

Maybe you are trying to transfer beyond the last char of lt_xml_stru, so you could try to transfer only the char needed. I don't have the ckf_t_xml type in my system so I can't test it but if you check the lt_xml_stru lenght then you can make TRANSFER lt_xml_stru TO pr_filename LENGHT str_lenght.

Marco

Read only

0 Likes
1,269

How do i calculate the length of last record?

the internal table contains non-readable characters (it's a BIN file) and it's made out of standard

xml related function modules.

For sure , having the last record length available i could try to use it, but honestly i tried

in many different ways but couldn't solve it.

If there's a way to calculate the length that could help but i have no idea how to do it.

I saw a few post who deals with using SCMS functions module but those are not available on 46c.

I tried copying one from ecc system but still couldn't get a damn solution!!

Read only

0 Likes
1,269

Wouldn't it be easier to make a text internal table and open a file in text mode?

IS there a way to make an internal table with ascii characters so i can transfer them as text?

Read only

0 Likes
1,269

I found somewhere that:   ld_size = lr_ostream->get_num_written_raw( ) gives back the exact length

of the entire xml document. Given that, how do i use it within the transfer in order to output only the

good charatcters and get rid of the junk?

Read only

bernardo_lee
Explorer
0 Likes
1,270

Hi Bruno,

Maybe you can use a different approach. Try to creat your xml fila as text and then convert it to xml.

The code would be something like this:

data: ixml                   type ref to if_ixml,
         xml_document  type ref to if_ixml_document.
     
data: lv_string   type string,
      lv_xstring  type xstring.

* Create the header
lv_string = '<Header>'.

* Attach data from the internal table
loop at i_table.
    concatenate lv_string i_table-field into lv_string.
     " add elements as needed

endloop.

* Attach the footer
concatenate lv_string '</Header>' into lv_string.

* Convert string to xstring
lv_xstring = cl_proxy_service=>cstring2xstring( lv_string ).

*create ixml dom document from xml xstring
        call function 'SDIXML_XML_TO_DOM'
          exporting
            xml           = lv_xstring
          importing
            document      = xml_document
          exceptions
            invalid_input = 1
            others        = 2.

Bernardo

Read only

0 Likes
1,269

PRoblem solved:

i was helped from this sap documentation:

Rendering into a table-based stream

When rendering the DOM
into a table-based stream, i.e. the XML stream is "line-wrapped" into an
unstructured internal table (based on type X), it might happen, that you
encounter some data in the last filled table line which seems to be garbage. You
are right with that assumption!

In order to find out
where the correct data stream ends and where the "garbage" starts, you have to
consider the exact length of the data written to your output stream. To get that
information, you have to call the method if_ixml_ostream->get_num_written_raw(). This method will tell you how many bytes have
been filled into the table. Taking this number module your table's line-length
will give you the number of valid characters in the last table line.

So here's how your code should look like:

types: begin of xml_line,

data(256) type x,

end of xml_line.

data: 
xml_table type table of xml_line,

xml_size  type i, oStream   type ref to  if_ixml_ostream.

...

oStream = streamFactory->create_ostream_itable ( xml_table );

document->render (ostream = oStream  recursive = 'X' ).

* use only the first xml_size bytes of the xml table!!

xml_size = oStream->get_num_written_raw(
).

BAsically i had to calculate te reminder of xml_size by 256.

then when i transfer the internal table to dataset , the very last transferred record will be like

TRANSFER save_xml_stru TO pr_filename LENGTH a, where A is the reminder.