Skip to Content
avatar image
Former Member

Convert XML string to internal table

Hi

My web service call returns a string XML. My task is to retrieve the values in the different nodes, preferably in an internal table. Previous I have used Simple Transformation, but I am not sure if this is possible this time, since the structure of the XML is changing (nodes can come 1 to n times).

Question: Are there any FMs that can convert my string XML to internal tables? What is the best practice to do in this situation?

regards Ole

Add comment
10|10000 characters needed characters exceeded

  • Get RSS Feed

4 Answers

  • avatar image
    Former Member
    Nov 05, 2013 at 01:37 PM

    Hi-

    To convert XML data to Internal tables you can use below sample code:

    **//TABLES AND DATATYPES DECLARATION

    TYPE-POOLS: abap, ixml.

    **// WORKAREA TO HOLD XML DATA //**

    TYPES: BEGIN OF ty_xdata,

    str(2550) TYPE c,

    END OF ty_xdata.

    DATA : xdata TYPE STANDARD TABLE OF ty_xdata,

    wa_xdata TYPE ty_xdata.

    **// INTERNAL TABLE AND WORKAREA OF TYPE DATABASE TABLE

    DATA: lt_itemp TYPE STANDARD TABLE OF zcitrus_table1,

    wa_itemp TYPE zcitrus_table1,

    gt_itemp TYPE STANDARD TABLE OF zcitrus_table1,

    gs_itemp TYPE zcitrus_table1.

    DATA: lt_itemp_g TYPE STANDARD TABLE OF zcitrus_table,

    wa_itemp_g TYPE zcitrus_table,

    gt_itemp_g TYPE STANDARD TABLE OF zcitrus_table,

    gs_itemp_g TYPE zcitrus_table.

    DATA : xmlupl TYPE string, " STRING VARIABLE USED FOR CONCATINATION

    v_file TYPE string, " STRING VARIABLE TO HOLD FILE PATH

    xstring TYPE xstring. " VARIABLE TO HOLD XSTRING DATA

    **// PARAMETERS REQUIRED FOR FM SMUM_XML_PARSER

    DATA : itab TYPE STANDARD TABLE OF smum_xmltb WITH HEADER LINE,

    wa_itab LIKE itab,

    return TYPE STANDARD TABLE OF bapiret2 .

    START-OF-SELECTION.

    **// PARAMETER TO HOLD FILE PATH

    PARAMETERS : p_file TYPE rlgrap-filename OBLIGATORY.

    **// PERFORMING VALIDATIONS ON P_FILE

    AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_file.

    CALL FUNCTION 'F4_FILENAME'

    EXPORTING

    program_name = syst-cprog

    dynpro_number = syst-dynnr

    * FIELD_NAME = ' '

    IMPORTING

    file_name = p_file.

    v_file = p_file.

    **// UPLOADING DATA FROM THE FILE //**

    IF v_file IS NOT INITIAL.

    CALL FUNCTION 'GUI_UPLOAD'

    EXPORTING

    filename = v_file

    filetype = 'ASC'

    TABLES

    data_tab = xdata.

    ENDIF.

    **// MOVING XML DATA TO THE XMLUPL //**

    LOOP AT xdata INTO wa_xdata.

    CONCATENATE xmlupl wa_xdata-str INTO xmlupl.

    ENDLOOP.

    **// FUNCTION MODULE TO CONVERT STRING TO XSTRING //**

    CALL FUNCTION 'SCMS_STRING_TO_XSTRING'

    EXPORTING

    text = xmlupl

    mimetype = 'SPACE '

    * ENCODING =

    IMPORTING

    buffer = xstring

    EXCEPTIONS

    failed = 1

    OTHERS = 2.

    **// FUNCTION MODULE TO UPLOAD DATA TO INTERNAL TABLE //**

    CALL FUNCTION 'SMUM_XML_PARSE'

    EXPORTING

    xml_input = xstring

    TABLES

    xml_table = itab[]

    return = return.

    Thanks,

    Venkat

    Add comment
    10|10000 characters needed characters exceeded

  • Aug 13, 2007 at 07:32 AM

    Try this solution -

    The XML

    In this weblog we will focus on retrieving data from a local XML file and store it in an internal table.

    We will start with an upload of a local XML file into a binary XML table and we will bind it to a XML input stream.

    Next we will parse the stream to a XML DOM object using a using an iXML factory.

    And finally we have a XML DOM Object and we can access its nodes to fill our table.

    The implementation

    In the implementation we will explain the steps of the process and at the end of the log you will find a complete source sample.

    To upload the XML file, you need the filename and you have to declare an internal binary table to store the uploaded XML file.

    TYPES: t_xml_line(1024) TYPE x.

    DATA: l_filename TYPE string,

    l_xml_table TYPE TABLE OF t_xml_line,

    l_xml_line TYPE t_xml_line,

    l_xml_table_size TYPE i.

    CALL METHOD cl_gui_frontend_services=>gui_upload

    EXPORTING

    filename = l_filename

    filetype = 'BIN'

    IMPORTING

    filelength = l_xml_table_size

    CHANGING

    data_tab = l_xml_table

    EXCEPTIONS

    OTHERS = 1.

    IF sy-subrc <> 0.

    MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno

    WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.

    ENDIF.

    When you have the XML file in a binary table, you can start to process the XML data. To do this we need an iXML factory which will help us create an input stream from the binary table.

    TYPE-POOLS: ixml.

    DATA: l_ixml TYPE REF TO if_ixml.

    l_ixml = cl_ixml=>create( ).

    This iXML factory can create a XML stream factory which actually creates an input stream based on the binary table.

    DATA: l_streamfactory TYPE REF TO if_ixml_stream_factory,

    l_istream TYPE REF TO if_ixml_istream.

    l_streamfactory = l_ixml->create_stream_factory( ).

    l_istream = l_streamfactory->create_istream_itable(

    table = l_xml_table

    size = l_xml_table_size ).

    Before creating the XML DOM object you have to create an empty document and a parser object. The document object will represent the DOM object and the parser is needed to convert the XML stream into a XML DOM object.

    DATA: l_document TYPE REF TO if_ixml_document,

    l_parser TYPE REF TO if_ixml_parser.

    l_document = l_ixml->create_document( ).

    l_parser = l_ixml->create_parser(

    stream_factory = l_streamfactory

    istream = l_istream

    document = l_document ).

    After having created the parser, the empty document and the input stream, you can start the conversion using the parse method of the parser. If the parsing failes, you can retrieve the error using the if_xml_parse_error interface.

    DATA: l_parse_error TYPE REF TO if_ixml_parse_error.

    IF l_parser->parse( ) NE 0.

    IF l_parser->num_errors( ) NE 0.

    ...

    l_parse_error = l_parser->get_error( index = l_index ).

    ...

    ENDIF.

    ENDIF.

    At this point you have to check if the DOM was really created and if so you can process the document.

    IF l_parser->is_dom_generating( ) EQ 'X'.

    PERFORM process_dom USING l_document.

    ENDIF.

    To process it you need to cast the document to a node interface object.

    DATA: node TYPE REF TO if_ixml_node,

    iterator TYPE REF TO if_ixml_node_iterator.

    node ?= document.

    CHECK NOT node IS INITIAL.

    When having the DOM object as a node object, you can use an iterator to “walk” trough the DOM object. To do this you have to create the iterator of the node object and get the root node using the get_next method of the iterator.

    iterator = node->create_iterator( ).

    node = iterator->get_next( ).

    Scrolling through the DOM, you can fill your internal table. The method get_type will tell you if the node is an element- of a text node. In the element node you will find the name of the element and the attribute which belong to the element node. In the text node, you will find the value of the element node.

    WHILE NOT node IS INITIAL.

    CASE node->get_type( ).

    WHEN if_ixml_node=>co_node_element.

    name = node->get_name( ).

    ...

    WHEN if_ixml_node=>co_node_text OR

    if_ixml_node=>co_node_cdata_section.

    value = node->get_value( ).

    ...

    ENDCASE.

    node = iterator->get_next( ).

    ENDWHILE.

    The attributes of an element will be available in a node map with the interface if_ixml_named_node_map. This interface can be used to read the names and values of the attributes in the element.

    nodemap = node->get_attributes( ).

    IF NOT nodemap IS INITIAL.

    count = nodemap->get_length( ).

    DO count TIMES.

    index = sy-index - 1.

    attr = nodemap->get_item( index ).

    name = attr->get_name( ).

    prefix = attr->get_namespace_prefix( ).

    value = attr->get_value( ).

    ...

    ENDDO.

    ENDIF.

    This finished the second step-of-three. As mentioned before the next log will focus on the use of SAP DOM within XI ABAP mapping.

    &----


    *& Report z_xit_xml_check

    &----


    REPORT z_xit_xml_check.

    TYPE-POOLS: ixml.

    TYPES: BEGIN OF t_xml_line,

    data(256) TYPE x,

    END OF t_xml_line.

    DATA: l_ixml TYPE REF TO if_ixml,

    l_streamfactory TYPE REF TO if_ixml_stream_factory,

    l_parser TYPE REF TO if_ixml_parser,

    l_istream TYPE REF TO if_ixml_istream,

    l_document TYPE REF TO if_ixml_document,

    l_node TYPE REF TO if_ixml_node,

    l_xmldata TYPE string.

    DATA: l_elem TYPE REF TO if_ixml_element,

    l_root_node TYPE REF TO if_ixml_node,

    l_next_node TYPE REF TO if_ixml_node,

    l_name TYPE string,

    l_iterator TYPE REF TO if_ixml_node_iterator.

    DATA: l_xml_table TYPE TABLE OF t_xml_line,

    l_xml_line TYPE t_xml_line,

    l_xml_table_size TYPE i.

    DATA: l_filename TYPE string.

    PARAMETERS: pa_file TYPE char1024 DEFAULT 'c:\temp\orders_dtd.xml'.

    • Validation of XML file: Only DTD included in xml document is supported

    PARAMETERS: pa_val TYPE char1 AS CHECKBOX.

    START-OF-SELECTION.

    • Creating the main iXML factory

    l_ixml = cl_ixml=>create( ).

    • Creating a stream factory

    l_streamfactory = l_ixml->create_stream_factory( ).

    PERFORM get_xml_table CHANGING l_xml_table_size l_xml_table.

    • wrap the table containing the file into a stream

    l_istream = l_streamfactory->create_istream_itable( table = l_xml_table

    size = l_xml_table_size ).

    • Creating a document

    l_document = l_ixml->create_document( ).

    • Create a Parser

    l_parser = l_ixml->create_parser( stream_factory = l_streamfactory

    istream = l_istream

    document = l_document ).

    • Validate a document

    IF pa_val EQ 'X'.

    l_parser->set_validating( mode = if_ixml_parser=>co_validate ).

    ENDIF.

    • Parse the stream

    IF l_parser->parse( ) NE 0.

    IF l_parser->num_errors( ) NE 0.

    DATA: parseerror TYPE REF TO if_ixml_parse_error,

    str TYPE string,

    i TYPE i,

    count TYPE i,

    index TYPE i.

    count = l_parser->num_errors( ).

    WRITE: count, ' parse errors have occured:'.

    index = 0.

    WHILE index < count.

    parseerror = l_parser->get_error( index = index ).

    i = parseerror->get_line( ).

    WRITE: 'line: ', i.

    i = parseerror->get_column( ).

    WRITE: 'column: ', i.

    str = parseerror->get_reason( ).

    WRITE: str.

    index = index + 1.

    ENDWHILE.

    ENDIF.

    ENDIF.

    • Process the document

    IF l_parser->is_dom_generating( ) EQ 'X'.

    PERFORM process_dom USING l_document.

    ENDIF.

    &----


    *& Form get_xml_table

    &----


    FORM get_xml_table CHANGING l_xml_table_size TYPE i

    l_xml_table TYPE STANDARD TABLE.

    • Local variable declaration

    DATA: l_len TYPE i,

    l_len2 TYPE i,

    l_tab TYPE tsfixml,

    l_content TYPE string,

    l_str1 TYPE string,

    c_conv TYPE REF TO cl_abap_conv_in_ce,

    l_itab TYPE TABLE OF string.

    l_filename = pa_file.

    • upload a file from the client's workstation

    CALL METHOD cl_gui_frontend_services=>gui_upload

    EXPORTING

    filename = l_filename

    filetype = 'BIN'

    IMPORTING

    filelength = l_xml_table_size

    CHANGING

    data_tab = l_xml_table

    EXCEPTIONS

    OTHERS = 19.

    IF sy-subrc <> 0.

    MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno

    WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.

    ENDIF.

    • Writing the XML document to the screen

    CLEAR l_str1.

    LOOP AT l_xml_table INTO l_xml_line.

    c_conv = cl_abap_conv_in_ce=>create( input = l_xml_line-data replacement = space ).

    c_conv->read( IMPORTING data = l_content len = l_len ).

    CONCATENATE l_str1 l_content INTO l_str1.

    ENDLOOP.

    l_str1 = l_str1+0(l_xml_table_size).

    SPLIT l_str1 AT cl_abap_char_utilities=>cr_lf INTO TABLE l_itab.

    WRITE: /.

    WRITE: /' XML File'.

    WRITE: /.

    LOOP AT l_itab INTO l_str1.

    REPLACE ALL OCCURRENCES OF cl_abap_char_utilities=>horizontal_tab IN

    l_str1 WITH space.

    WRITE: / l_str1.

    ENDLOOP.

    WRITE: /.

    ENDFORM. "get_xml_table

    &----


    *& Form process_dom

    &----


    FORM process_dom USING document TYPE REF TO if_ixml_document.

    DATA: node TYPE REF TO if_ixml_node,

    iterator TYPE REF TO if_ixml_node_iterator,

    nodemap TYPE REF TO if_ixml_named_node_map,

    attr TYPE REF TO if_ixml_node,

    name TYPE string,

    prefix TYPE string,

    value TYPE string,

    indent TYPE i,

    count TYPE i,

    index TYPE i.

    node ?= document.

    CHECK NOT node IS INITIAL.

    ULINE.

    WRITE: /.

    WRITE: /' DOM-TREE'.

    WRITE: /.

    IF node IS INITIAL. EXIT. ENDIF.

    • create a node iterator

    iterator = node->create_iterator( ).

    • get current node

    node = iterator->get_next( ).

    • loop over all nodes

    WHILE NOT node IS INITIAL.

    indent = node->get_height( ) * 2.

    indent = indent + 20.

    CASE node->get_type( ).

    WHEN if_ixml_node=>co_node_element.

    • element node

    name = node->get_name( ).

    nodemap = node->get_attributes( ).

    WRITE: / 'ELEMENT :'.

    WRITE: AT indent name COLOR COL_POSITIVE INVERSE.

    IF NOT nodemap IS INITIAL.

    • attributes

    count = nodemap->get_length( ).

    DO count TIMES.

    index = sy-index - 1.

    attr = nodemap->get_item( index ).

    name = attr->get_name( ).

    prefix = attr->get_namespace_prefix( ).

    value = attr->get_value( ).

    WRITE: / 'ATTRIBUTE:'.

    WRITE: AT indent name COLOR COL_HEADING INVERSE, '=',

    value COLOR COL_TOTAL INVERSE.

    ENDDO.

    ENDIF.

    WHEN if_ixml_node=>co_node_text OR

    if_ixml_node=>co_node_cdata_section.

    • text node

    value = node->get_value( ).

    WRITE: / 'VALUE :'.

    WRITE: AT indent value COLOR COL_GROUP INVERSE.

    ENDCASE.

    • advance to next node

    node = iterator->get_next( ).

    ENDWHILE.

    ENDFORM. "process_dom

    Regards,

    Amit

    Reward all helpful replies.

    Add comment
    10|10000 characters needed characters exceeded

    • Hi, You can use cl_bcs_convert=>string_to_xstring¬† To convert your string¬† .¬† And then do the xml stuf.¬† example:

      TYPES: BEGIN OF tp_alv_data_1 .

      TYPES: date        TYPE char32 ,
             name        TYPE char32 ,
             currency    TYPE char32 ,
             country     TYPE char32 ,
             rate        TYPE char32 ,
             ukurs       TYPE tcurr-ukurs ,
             change      TYPE char32 .
      TYPES: END OF tp_alv_data_1 .

      *

      TYPES: tp_alv_data_1_tab TYPE STANDARD TABLE OF tp_alv_data_1  .


      DATA: it_alv_data_1 TYPE tp_alv_data_1_tab  .

      *----------------------------------------------------------------------*
      FORM do_xml_parse_1
        USING
          xml_string TYPE xstring
        CHANGING
          it_alv_data_1 TYPE tp_alv_data_1_tab .
      
        IF xml_string IS INITIAL .
          RETURN .
        ENDIF .
      
        DATA: st_alv_data_1 LIKE LINE OF it_alv_data_1 .
      
        g_ixml = cl_ixml=>create( ).
      
        DATA: streamfactory TYPE REF TO if_ixml_stream_factory.
      
        streamfactory = g_ixml->create_stream_factory( ).
      
        DATA: istream TYPE REF TO if_ixml_istream.
      
        istream  = streamfactory->create_istream_xstring( string = xml_string ).
      
        DATA: document TYPE REF TO if_ixml_document.
      
        document = g_ixml->create_document( ) .
      
        DATA: parser TYPE REF TO if_ixml_parser.
      
        parser = g_ixml->create_parser( stream_factory = streamfactory
                                        istream        = istream
                                        document       = document ).
      
        parser->parse( ).
      
      *------------------------------
      
        DATA: date  TYPE string .
        DATA: name  TYPE string .
        DATA: value TYPE string .
      
      *------------------------------
      
        DATA: nodes_x TYPE REF TO if_ixml_node_collection .
        DATA: node_x  TYPE REF TO if_ixml_node .
      
        nodes_x = document->get_elements_by_tag_name( name = 'LAST_UPDATE' ).
      
        node_x = nodes_x->get_item( 0 ) .
      
        name  = node_x->get_name( ) .
        date  = node_x->get_value( ) .
      
        st_alv_data_1-date = node_x->get_value( ) .
      
      *------------------------------
      
        DATA: length_0 TYPE i .
        DATA: nodes_0 TYPE REF TO if_ixml_node_collection.
        DATA: node_0  TYPE REF TO if_ixml_node .
      
        DATA: length_1 TYPE i .
        DATA: nodes_1 TYPE REF TO if_ixml_node_list .
        DATA: node_1  TYPE REF TO if_ixml_node .
      
        nodes_0 = document->get_elements_by_tag_name( name = 'CURRENCY' ).
        length_0 = nodes_0->get_length( ) .
      
        DATA: index TYPE i .
      
        DO length_0 TIMES .
      
          index = sy-index - 1 .
      
          node_0 = nodes_0->get_item( index ) .
      
          name  = node_0->get_name( ) .
          value = space .
      
          nodes_1 = node_0->get_children( ) .
          length_1 = nodes_1->get_length( ).
      
          DO length_1 TIMES .
      
            index = sy-index - 1 .
      
            node_1 = nodes_1->get_item( index ).
      
            name  = node_1->get_name( ) .
            value = node_1->get_value( ) .
      
            CASE name .
              WHEN 'NAME' .
                st_alv_data_1-name = value .
              WHEN 'CURRENCYCODE' .
                st_alv_data_1-currency = value .
              WHEN 'COUNTRY' .
                st_alv_data_1-country = value .
              WHEN 'RATE' .
                st_alv_data_1-rate  = value .
                st_alv_data_1-ukurs = value .
              WHEN 'CHANGE' .
                st_alv_data_1-change = value .
            ENDCASE .
      
          ENDDO .
      
          APPEND st_alv_data_1 TO it_alv_data_1 .
      
        ENDDO .
      
      ENDFORM .                    "do_xml_parse_1
      *----------------------------------------------------------------------*
      
      
           Regards.
  • avatar image
    Former Member
    Aug 13, 2007 at 07:34 AM

    Hi,

    Try the following. These are the general practices. Hope the best one helps you.

    You can write code like similar...

    DATA xml_string TYPE string.

    DATA source1(10) TYPE c VALUE 'Field1'.

    DATA source2(10) TYPE c VALUE 'Field2'.

    CALL TRANSFORMATION ...

    SOURCE root1 = source1

    root2 = source2

    RESULT XML xml_string.

    For more help see

    http://help.sap.com/saphelp_nw04/helpdata/en/e3/7d4719ca581441b6841f1054ff1326/content.htm

    Or You can look for this option below:

    Check these standard demo transactions:

    SXSLTDEMO1

    SSTDEMO1

    SSTDEMO2

    Here you can see an example how export data from ABAP to XML and XML data to ABAP.

    Thanks,

    Samantak.

    <b>Rewards points for useful answers.</b>

    Add comment
    10|10000 characters needed characters exceeded

  • avatar image
    Former Member
    Nov 05, 2013 at 11:56 AM

    This message was moderated.

    Add comment
    10|10000 characters needed characters exceeded