Lyriance-labs

Welcome on Lyriance-labs. A site powered by the Lyriance team.

Feel free to create your account and share your knowledge...

Home SAP Tech ABAP ABAP - Program examples Utils and Tools All you need to deal with XML

All you need to deal with XML

E-mail Print PDF
*&---------------------------------------------------------------------*
*& Report  ZUTILS_INT_XML_TEST                                         *
*&                                                                     *
*&---------------------------------------------------------------------*
*&                                                                     *
*&                                                                     *
*&---------------------------------------------------------------------*

REPORT  zutils_int_xml_test.

INCLUDE zutils_in_int_top.

" XML Includes
INCLUDE zutils_int_in_xml_top.
INCLUDE zutils_int_in_xml_parser.
INCLUDE zutils_int_in_xml_f01.

TYPES: BEGIN OF ty_struct2,
         field121(1) TYPE c,
         field122(255) TYPE c,
       END OF ty_struct2.

TYPES: BEGIN OF ty_struct1,
         &attr1 TYPE C,
         &attr2 TYPE string,
         field11 TYPE string,
         field12 TYPE ty_struct2 OCCURS 0,
       END OF ty_struct1.

TYPES: BEGIN OF ty_struct,
         field1 TYPE ty_struct1,
       END OF ty_struct.
DATA: gt_struct TYPE ty_struct.


START-OF-SELECTION.
  init_xml_string.
  open_tag_attr 'FIELD1' 'attr1="c" attr2="Test"'.
  define_tag 'FIELD11' 'Test de chaîne de caractère'.
  open_tag 'FIELD12'.
  define_tag 'FIELD121' 'E'.
  define_tag 'FIELD122' 'test'.
  close_tag 'FIELD12'.
  open_tag 'FIELD12'.
  define_tag 'FIELD12A' 'E'.
  define_tag 'FIELD12B' 'test'.
  close_tag 'FIELD12'.
  close_tag 'FIELD1'.
  close_xml_string.

  PERFORM xml_to_data CHANGING gt_struct.

  gt_struct = gt_struct.
  zcl_utils_xml_parser=>gt_xml_parser_msg = zcl_utils_xml_parser=>gt_xml_parser_msg.

  CLEAR gt_data. REFRESH gt_data.

  " Transform the data structure in a XML string
  PERFORM data_to_xml USING gt_struct.

  LOOP AT gt_DATA.
    WRITE: /, gt_data.
  ENDLOOP.
 
  
 
 
 
 
 
*&---------------------------------------------------------------------*
*& Include           ZUTILS_IN_INT_TOP
*&
*&---------------------------------------------------------------------*
*& Author : Lyriance
*& Date : 21/10/2008
*& Purpose :
*&---------------------------------------------------------------------*

*----------------------------------------------------------------------*
* DATA Declaration
*----------------------------------------------------------------------*
TYPES : BEGIN OF ty_data,
          txt LIKE zutils_1024-txt,
        END OF ty_data.
DATA: gt_data TYPE STANDARD TABLE OF ty_data WITH HEADER LINE.

DATA: gt_messages TYPE STANDARD TABLE OF zutils_message WITH HEADER LINE.

DATA: gd_service(255) TYPE C.

*----------------------------------------------------------------------*
* Constants Declaration
*----------------------------------------------------------------------*
CONSTANTS: k_service_delimit TYPE C VALUE '#'.

*----------------------------------------------------------------------*
* Macros
*----------------------------------------------------------------------*
DEFINE get_message.
  gt_messages-type = &1.
  perform get_message using sy-langu 'ZUTILS_MESSAGE' &2 &3 &4 &5 &6
                      changing gt_messages-txt.
  append gt_messages. clear gt_messages.
END-OF-DEFINITION.
 
 
 
 
 
 
 
 
*&---------------------------------------------------------------------*
*&  Include           ZUTILS_INT_IN_XML_PARSER                         *
*&---------------------------------------------------------------------*

*----------------------------------------------------------------------*
*       CLASS zcl_utils_xml_parser DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS zcl_utils_xml_parser DEFINITION.
*----------------------------------------------------------------------*
* PUBLIC SECTION
*----------------------------------------------------------------------*
  PUBLIC SECTION.
    " Current Path in the target structure
    TYPES: BEGIN OF ty_path,
             name(255) TYPE c,
           END OF ty_path.

    " Messages
    TYPES: BEGIN OF ty_xml_parser_msg,
         type(1) TYPE c,
         text(255) TYPE c,
       END OF ty_xml_parser_msg.
    CLASS-DATA: gt_xml_parser_msg TYPE STANDARD TABLE OF ty_xml_parser_msg.

    " Global datas
    DATA: gd_ixml       TYPE REF TO if_ixml,
          gd_factory    TYPE REF TO if_ixml_stream_factory,
          gd_parser     TYPE REF TO if_ixml_parser,
          gd_istream    TYPE REF TO if_ixml_istream,
          gd_document   TYPE REF TO if_ixml_document,             " Document
          gd_node       TYPE REF TO if_ixml_node,                 " Name of the current XML node
          gd_iterator   TYPE REF TO if_ixml_node_iterator,        " Iterator to get the node

          gd_ex         TYPE REF TO cx_root.                      " Exception

    " Public methods
    METHODS: parse_xml_to_data IMPORTING p_xml TYPE any
                                         p_size TYPE i
                               CHANGING  p_struct TYPE any.

    METHODS: parse_data_to_xml IMPORTING p_struct TYPE any.

*----------------------------------------------------------------------*
* PRIVATE SECTION
*----------------------------------------------------------------------*
  PRIVATE SECTION.
    " For data to xml
    METHODS: process_struct_to_xml    IMPORTING  p_struct    TYPE any,
             process_simple_to_xml    IMPORTING  p_name      TYPE abap_compname
                                                 p_type      TYPE c
                                                 p_field     TYPE any,
             process_table_to_xml     IMPORTING  p_struct_name TYPE abap_compname
                                                 p_table     TYPE any.

    " For xml to data
    METHODS: process_dom_to_data      CHANGING  p_struct    TYPE any,
             process_dom_to_struct    IMPORTING p_exit_node TYPE string
                                                p_exit_node2 TYPE string
                                      CHANGING  p_struct    TYPE any,
             process_dom_to_struct_of_table     IMPORTING p_table_name     TYPE string
                                                CHANGING  p_table    TYPE any,
             process_get_attributes   CHANGING  p_struct    TYPE any,
             process_push_path        IMPORTING p_name      TYPE any
                                      CHANGING  p_path      TYPE STANDARD TABLE,
             process_pop_path         CHANGING  p_path      TYPE STANDARD TABLE,
             process_get_path_length  IMPORTING p_path      TYPE STANDARD TABLE
                                      RETURNING value(p_length) TYPE i,
             process_get_value        IMPORTING p_type TYPE c
                                                p_value TYPE any
                                      CHANGING  p_field TYPE any,
             process_get_node_name    RETURNING value(p_node_name) TYPE string,
             process_get_next_node_name    RETURNING value(p_next_node_name) TYPE string,
             process_message          IMPORTING p_type TYPE c
                                                p_text TYPE string.
ENDCLASS.                    "zcl_utils_xml_parser DEFINITION



*----------------------------------------------------------------------*
*       CLASS zcl_utils_xml_parser IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS zcl_utils_xml_parser IMPLEMENTATION.

*----------------------------------------------------------------------*
* Main method to parse data to XML
*----------------------------------------------------------------------*
  METHOD parse_data_to_xml.
    init_xml_string.

    process_struct_to_xml( EXPORTING p_struct = p_struct ).

    close_xml_string.
  ENDMETHOD.                    "parse_data_to_xml


  METHOD process_struct_to_xml.
    DATA: l_struct TYPE REF TO cl_abap_structdescr,
          lt_comp  TYPE abap_compdescr_tab,
          l_comp   TYPE abap_compdescr,
          l_type   TYPE c.

    FIELD-SYMBOLS: <fs_field> TYPE ANY.

    " Get the structure components
    l_struct ?= cl_abap_typedescr=>describe_by_data( p_struct ).
    lt_comp = l_struct->components.

    LOOP AT lt_comp INTO l_comp.
      IF NOT l_comp-name IS INITIAL.
        ASSIGN COMPONENT l_comp-name OF STRUCTURE p_struct TO <fs_field>.

        IF NOT <fs_field> IS ASSIGNED.
          EXIT.
        ELSE.
          DESCRIBE FIELD <fs_field> TYPE l_type.
          CASE l_type.
              " If simple type
            WHEN 'C' OR 'D' OR 'N' OR 'T' OR 'I' OR 'P' OR 'F' OR 'g' OR 'x'.
              process_simple_to_xml( EXPORTING p_name = l_comp-name
                                               p_type = l_type
                                               p_field = <fs_field> ).

              " Structure
            WHEN 'v' OR 'u'.
              open_tag l_comp-name.

              process_struct_to_xml( EXPORTING p_struct = <fs_field> ).

              close_tag l_comp-name.

              " Table.
            WHEN 'h'.
              process_table_to_xml( EXPORTING p_struct_name = l_comp-name
                                              p_table = <fs_field> ).

          ENDCASE.
        ENDIF.

      ENDIF.
    ENDLOOP.
  ENDMETHOD.                    "process_struct_to_xml


  METHOD process_simple_to_xml.

    CASE p_type.
      WHEN 'C' OR 'N' OR 'I' OR 'g'.
        define_tag p_name p_field.

      WHEN OTHERS.

    ENDCASE.
  ENDMETHOD.                    "process_simple_to_xml


  METHOD process_table_to_xml.
    DATA: l_ref TYPE REF TO data.

    FIELD-SYMBOLS: <fs_table> TYPE STANDARD TABLE.
    FIELD-SYMBOLS: <fs_struct> TYPE ANY.

    ASSIGN p_table TO <fs_table>.

    IF <fs_table> IS ASSIGNED.
      CREATE DATA l_ref LIKE LINE OF <fs_table>.
      ASSIGN l_ref->* TO <fs_struct>.

      LOOP AT <fs_table> ASSIGNING <fs_struct>.
        IF <fs_struct> IS ASSIGNED.
          open_tag p_struct_name.
          process_struct_to_xml( EXPORTING p_struct = <fs_struct> ).
          close_tag p_struct_name.
        ENDIF.
      ENDLOOP.
    ENDIF.
  ENDMETHOD.                    "process_table_to_xml


*----------------------------------------------------------------------*
* Main method to parse XML into a data structure
*----------------------------------------------------------------------*
  METHOD parse_xml_to_data.
    DATA: l_type       TYPE c.

    gd_ixml = cl_ixml=>create( ).
    gd_factory = gd_ixml->create_stream_factory( ).
    gd_document = gd_ixml->create_document( ).

    DESCRIBE FIELD p_xml TYPE l_type.
    CASE l_type.
      WHEN 'y'.
        gd_istream  = gd_factory->create_istream_xstring( string = p_xml ).
      WHEN 'h'.
        gd_istream  = gd_factory->create_istream_itable( table = p_xml
                                                         size  = p_size ).
      WHEN OTHERS.

    ENDCASE.

    " XML TO DOM transformation
    gd_parser = gd_ixml->create_parser( stream_factory = gd_factory
                                        istream = gd_istream
                                        document = gd_document ).

    " DOM to DATA transformation
    IF gd_parser->parse( ) EQ 0.
      process_dom_to_data( CHANGING   p_struct = p_struct ).
    ELSE.
      process_message( EXPORTING p_type = 'E'
                                 p_text = 'Error while XML to DOM transformation. Bad XML string.' ).
    ENDIF.
  ENDMETHOD.                    "parse_xml_to_data

*----------------------------------------------------------------------*
* Convert Dom TO Data
*----------------------------------------------------------------------*
  METHOD process_dom_to_data.
    IF gd_document IS INITIAL.
      RETURN.
    ENDIF.

    " Iterator
    gd_iterator = gd_document->create_iterator( ).

    " Fill the main structure
    gd_node = gd_iterator->get_next( ).
    process_dom_to_struct( EXPORTING p_exit_node = ''
                                     p_exit_node2 = ''
                           CHANGING p_struct = p_struct ).
  ENDMETHOD.                    "process_dom

*----------------------------------------------------------------------*
* Process a structure of a table
*----------------------------------------------------------------------*
  METHOD process_dom_to_struct_of_table.
    DATA: l_ref TYPE REF TO data,
          l_name     TYPE string,
          l_end_at   TYPE string.

    FIELD-SYMBOLS: <fs_table> TYPE STANDARD TABLE.
    FIELD-SYMBOLS: <fs_struct> TYPE ANY.

    ASSIGN p_table TO <fs_table>.

    IF <fs_table> IS ASSIGNED.
      CREATE DATA l_ref LIKE LINE OF <fs_table>.
      ASSIGN l_ref->* TO <fs_struct>.

      IF <fs_struct> IS ASSIGNED.

        l_end_at = process_get_next_node_name( ).
        l_name = p_table_name.

        " Fill the table
        WHILE l_name EQ p_table_name.
          gd_node = gd_iterator->get_next( ).
          process_dom_to_struct( EXPORTING p_exit_node = p_table_name
                                           p_exit_node2 = l_end_at
                                 CHANGING p_struct = <fs_struct> ).
          APPEND <fs_struct> TO <fs_table>.
          CLEAR <fs_struct>.

          IF NOT gd_node IS INITIAL.
            l_name = process_get_node_name( ).
            l_end_at = process_get_next_node_name( ).
          ELSE.
            EXIT.
          ENDIF.
        ENDWHILE.
      ENDIF.
    ENDIF.

  ENDMETHOD.                    "process_dom_to_struct_of_table

*----------------------------------------------------------------------*
* Process a structure
*----------------------------------------------------------------------*
  METHOD process_dom_to_struct.
    DATA: lt_path        TYPE STANDARD TABLE OF ty_path,
          l_path_length  TYPE i,
          l_path_name    TYPE string,
          l_ex           TYPE string,
          l_value        TYPE string,
          l_name         TYPE string,
          l_temp_name    TYPE string,
          l_type         TYPE c.

    FIELD-SYMBOLS: <fs_current> TYPE ANY,
                   <fs_node> TYPE ANY.

    " Initialization
    ASSIGN p_struct TO <fs_current>.


*   Loop on all the xml nodes
    WHILE NOT gd_node IS INITIAL.
      " Node name
      l_name = process_get_node_name( ).

      " Process the XML node
      CASE gd_node->get_type( ).

*       Node with children
        WHEN if_ixml_node=>co_node_element.
          " Initialization
          ASSIGN p_struct TO <fs_current>.
          UNASSIGN <fs_node>.

          " Get the current position in the path of the target structure
          l_path_length = process_get_path_length( p_path = lt_path ).
          IF l_path_length GT 0.
            LOOP AT lt_path INTO l_path_name.
              ASSIGN COMPONENT l_path_name OF STRUCTURE <fs_current> TO <fs_current>.
            ENDLOOP.
          ENDIF.

          " Check if the node exists in the target structure and assign it
          " If not exists we go back to the upper level in the path
          WHILE l_path_length GE 0 AND NOT <fs_node> IS ASSIGNED.
            ASSIGN COMPONENT l_name OF STRUCTURE <fs_current> TO <fs_node>.
            IF <fs_node> IS ASSIGNED.
              ASSIGN <fs_node> TO <fs_current>.
              process_push_path( EXPORTING p_name = l_name
                                 CHANGING  p_path = lt_path ).
            ELSE.
              process_pop_path( CHANGING  p_path = lt_path ).
              SUBTRACT 1 FROM l_path_length.
              ASSIGN p_struct TO <fs_current>.
              IF l_path_length GT 0.
                LOOP AT lt_path INTO l_path_name.
                  ASSIGN COMPONENT l_path_name OF STRUCTURE <fs_current> TO <fs_current>.
                ENDLOOP.
              ELSE.
                ASSIGN p_struct TO <fs_current>.
              ENDIF.

              UNASSIGN <fs_node>.
            ENDIF.
          ENDWHILE.


          " If it's a table we do a recursive call to fill a record and append it to the table
          DESCRIBE FIELD <fs_current> TYPE l_type.
          CASE l_type.
            WHEN 'h'.
              process_dom_to_struct_of_table( EXPORTING p_table_name = l_name
                                              CHANGING p_table = <fs_current> ).
              process_pop_path( CHANGING  p_path = lt_path ).

            WHEN OTHERS.
          ENDCASE.


          " Attributes
          process_get_attributes( CHANGING p_struct = <fs_current> ).



*       Value of a node
        WHEN if_ixml_node=>co_node_text OR if_ixml_node=>co_node_cdata_section.
          " Get the value
          l_value = gd_node->get_value( ).

          " Try to get the value
          DESCRIBE FIELD <fs_current> TYPE l_type.
          CASE l_type.

              " String, chars, numéric, ...
            WHEN 'C' OR 'D' OR 'N' OR 'T' OR 'I' OR 'P' OR 'F' OR 'g' OR 'y'.
              TRY.
                  process_get_value( EXPORTING p_type = l_type
                                               p_value = l_value
                                     CHANGING  p_field = <fs_current> ).
                CATCH cx_root INTO gd_ex.
                  l_ex = gd_ex->get_text( ).
                  process_message( EXPORTING p_type = 'E'
                                             p_text = l_ex ).
              ENDTRY.

              process_pop_path( CHANGING  p_path = lt_path ).

              " Other types
            WHEN OTHERS.
              CONCATENATE 'The target field' l_name 'has a bad type' INTO l_ex SEPARATED BY space.
              process_message( EXPORTING p_type = 'E'
                                         p_text = l_ex ).
          ENDCASE.
      ENDCASE.

      " Check if it's the end of an internal table's record
      IF NOT p_exit_node IS INITIAL AND NOT p_exit_node2 IS INITIAL.
        gd_node = gd_iterator->get_next( ).
        l_temp_name = process_get_node_name( ).
        IF NOT l_temp_name IS INITIAL AND ( l_temp_name EQ p_exit_node OR l_temp_name EQ p_exit_node2 ).
          EXIT.
        ENDIF.

        " Simple next node
      ELSE.
        l_temp_name = process_get_node_name( ).
        IF l_temp_name EQ l_name.
          gd_node = gd_iterator->get_next( ).
        ENDIF.
      ENDIF.

      CLEAR l_temp_name.
    ENDWHILE.
  ENDMETHOD.                    "process_dom_to_struct

*----------------------------------------------------------------------*
* Methods to get attributes of a node
*----------------------------------------------------------------------*
  METHOD process_get_attributes.
    DATA: l_nodemap  TYPE REF TO if_ixml_named_node_map,
          l_attr     TYPE REF TO if_ixml_node,
          l_value    TYPE string,
          l_name     TYPE string,
          l_count    TYPE i,
          l_index    TYPE i,
          l_type     TYPE c.

    FIELD-SYMBOLS: <fs_attr> TYPE ANY.

    IF NOT gd_node IS INITIAL.
      l_nodemap = gd_node->get_attributes( ).
      IF NOT l_nodemap IS INITIAL.
        l_count = l_nodemap->get_length( ).

        " Loop on attributes
        DO l_count TIMES.
          l_index = sy-index - 1.
          l_attr = l_nodemap->get_item( l_index ).
          l_name = l_attr->get_name( ).
          l_value = l_attr->get_value( ).

          CONCATENATE '&' l_name INTO l_name IN CHARACTER MODE.
          TRANSLATE l_name TO UPPER CASE.
          ASSIGN COMPONENT l_name OF STRUCTURE p_struct TO <fs_attr>.
          IF <fs_attr> IS ASSIGNED.
            DESCRIBE FIELD p_struct TYPE l_type.
            process_get_value( EXPORTING p_type  = l_type
                                         p_value = l_value
                               CHANGING  p_field = <fs_attr> ).
          ENDIF.
        ENDDO.
      ENDIF.
    ENDIF.
  ENDMETHOD.                    "process_get_attributes


*----------------------------------------------------------------------*
* Methods to manage the position path in the target structure
*----------------------------------------------------------------------*
  METHOD process_push_path.
    APPEND p_name TO p_path.
  ENDMETHOD.                    "process_push_node

  METHOD process_pop_path.
    DATA: l_lines TYPE i.

    DESCRIBE TABLE p_path LINES l_lines.
    IF l_lines GT 0.
      DELETE p_path INDEX l_lines.
    ENDIF.
  ENDMETHOD.                    "process_pop_node

  METHOD process_get_path_length.
    DATA: l_lines TYPE i.

    DESCRIBE TABLE p_path LINES l_lines.
    p_length = l_lines.
  ENDMETHOD.                    "process_pop_node_length

*----------------------------------------------------------------------*
* Get the value of a XML node or an attribute
*----------------------------------------------------------------------*
  METHOD process_get_value.
    DATA l_length TYPE i.
    " Length of the value
    l_length = strlen( p_value ).

    " Get value
    CASE p_type.
        " Dates
      WHEN 'D'.

        CASE l_length.
          WHEN 10.
            IF p_value CO '0123456789.-/ '.
              DATA: l_date(10) TYPE c.

              MOVE p_value(10) TO l_date.
              TRANSLATE l_date USING '/.'.
              TRANSLATE l_date USING '-.'.
              TRANSLATE l_date USING ' .'.

              IF l_date CP '++.++.++++'.
                CONCATENATE l_date+6(4) l_date+3(2) l_date(2) INTO p_field.
              ELSEIF l_date CP '++++.++.++'.
                CONCATENATE l_date(4) l_date+5(2) l_date+7(2) INTO p_field.
              ENDIF.
            ENDIF.

          WHEN 8.
            IF p_value CO '0123456789'.
              CONCATENATE p_value+4(4) p_value+2(2) p_value(2) INTO p_field.
            ENDIF.
          WHEN OTHERS.
        ENDCASE.

        " Heures
      WHEN 'T'.
        CASE l_length.
          WHEN 8.
            DATA: l_time(8) TYPE c.
            IF p_value CO '0123456789:- '.
              MOVE p_value(8) TO l_time.
              TRANSLATE l_time USING ': '.
              TRANSLATE l_time USING '- '.
              CONDENSE l_time NO-GAPS.

              MOVE l_time(6) TO p_field.
            ENDIF.
          WHEN 6.
            IF p_value CO '0123456789'.
              MOVE p_value TO p_field.
            ENDIF.
          WHEN OTHERS.
        ENDCASE.

        " Tout autres types de données
      WHEN OTHERS.
        MOVE p_value TO p_field.

    ENDCASE.
  ENDMETHOD.                    "process_get_value


*----------------------------------------------------------------------*
* Methods to get node's name
*----------------------------------------------------------------------*
  METHOD process_get_node_name.
    IF NOT gd_node IS INITIAL.
      p_node_name = gd_node->get_name( ).
      TRANSLATE p_node_name TO UPPER CASE.
    ENDIF.
  ENDMETHOD.                    "process_get_node_name

  METHOD process_get_next_node_name.
    DATA: l_next_node TYPE REF TO if_ixml_node.
    IF NOT gd_node IS INITIAL.
      l_next_node = gd_node->get_next( ).
      IF NOT l_next_node IS INITIAL.
        p_next_node_name = l_next_node->get_name( ).
        TRANSLATE p_next_node_name TO UPPER CASE.
      ELSE.
        p_next_node_name = ''.
      ENDIF.
    ENDIF.
  ENDMETHOD.                    "process_get_next_node_name

*----------------------------------------------------------------------*
* Add a message
*----------------------------------------------------------------------*
  METHOD process_message.
    DATA: l_xml_parser_msg TYPE ty_xml_parser_msg.

    MOVE p_type TO l_xml_parser_msg-type.
    MOVE p_text TO l_xml_parser_msg-text.
    APPEND l_xml_parser_msg TO gt_xml_parser_msg.
  ENDMETHOD.                    "process_message
ENDCLASS.                    "zcutils_xml_parser IMPLEMENTATION
 
 
 
 
 
 
 
 
*&---------------------------------------------------------------------*
*&  Include           ZUTILS_INT_IN_XML_TOP                            *
*&---------------------------------------------------------------------*

TYPE-POOLS: abap.

*----------------------------------------------------------------------*
* Datas
*----------------------------------------------------------------------*
DATA: gd_pos TYPE i,
      gd_max TYPE i.

*----------------------------------------------------------------------*
* XML Declaration
*----------------------------------------------------------------------*
DATA: tag_begin_list_xml(80) VALUE '<?xml version="1.0" encoding="iso-8859-1"?><DATAS>'.
DATA: tag_end_list_xml(80) VALUE '</DATAS>'.

*----------------------------------------------------------------------*
* XML Macros
*----------------------------------------------------------------------*
DEFINE init_xml_string.
  gd_pos = 0.
  DESCRIBE FIELD gt_data LENGTH gd_max In CHARACTER MODE.
  refresh gt_data. clear  gt_data.

  perform fill_data using tag_begin_list_xml.
END-OF-DEFINITION.

DEFINE open_tag.
  perform open_tag using &1.
END-OF-DEFINITION.

DEFINE open_tag_attr.
  perform open_tag_attr using &1 &2.
END-OF-DEFINITION.

DEFINE put_value.
  perform put_value using &1.
END-OF-DEFINITION.

DEFINE close_tag.
  perform close_tag using &1.
END-OF-DEFINITION.

DEFINE define_tag.
  open_tag &1.
  put_value &2.
  close_tag &1.
END-OF-DEFINITION.

DEFINE close_xml_string.
  perform fill_data using tag_end_list_xml.
  append gt_data TO gt_data. clear gt_data.
END-OF-DEFINITION. 
 
 
 
 
 
 
*&---------------------------------------------------------------------*
*&  Include           ZUTILS_INT_IN_XML_F01                            *
*&---------------------------------------------------------------------*

*&---------------------------------------------------------------------*
*&      Form  open_tag
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->P_TAG      text
*----------------------------------------------------------------------*
FORM open_tag USING p_tag.
  DATA: l_tag(255) TYPE c.

  CONCATENATE '<' p_tag '>' INTO l_tag.

  PERFORM fill_data USING l_tag.
ENDFORM.                    "OPEN_TAG

*&---------------------------------------------------------------------*
*&      Form  open_tag_attr
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->P_TAB      text
*      -->P_ATTR     text
*----------------------------------------------------------------------*
FORM open_tag_attr USING p_tag
                         p_attr.
  DATA: l_tag(255) TYPE c.

  CONCATENATE '<' p_tag INTO l_tag.

  IF NOT p_attr IS INITIAL.
    CONCATENATE l_tag p_attr INTO l_tag SEPARATED BY space.
  ENDIF.

  CONCATENATE l_tag '>' INTO l_tag.

  PERFORM fill_data USING l_tag.
ENDFORM.                    "OPEN_TAG

*&---------------------------------------------------------------------*
*&      Form  put_value
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->P_VALUE    text
*----------------------------------------------------------------------*
FORM put_value USING p_value.
  DATA: l_value LIKE gt_data,
        l_size TYPE I.

  MOVE p_value TO l_value.

  IF l_value CA '&<>/äëïöüéèàùâêîôû'''.
    l_size = gd_max - 14.
    CONCATENATE '<![CDATA[' l_value(l_size) ']]>' INTO l_value.
  ENDIF.

  PERFORM fill_data USING l_value.
ENDFORM.                    "put_value


*&---------------------------------------------------------------------*
*&      Form  close_tag
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->P_TAG      text
*----------------------------------------------------------------------*
FORM close_tag USING  p_tag.
  DATA: l_tag(255) TYPE c.

  CONCATENATE '</' p_tag '>' INTO l_tag.

  PERFORM fill_data USING l_tag.
ENDFORM.                                    " CLOSE_TAG

*&---------------------------------------------------------------------*
*&      Form  fill_data
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->P_VALUE    text
*----------------------------------------------------------------------*
FORM fill_data USING  p_value.
  DATA: l_value TYPE string,
        l_length TYPE i,
        l_newpos TYPE i,
        l_remind TYPE i,
        l_shift TYPE i.

  MOVE p_value TO l_value.

  " Length of the string to add
  l_length = STRLEN( l_value ).

  " Add the string and calculate new position
  gt_data+gd_pos = l_value.
  l_newpos = gd_pos + l_length.

  " If the new position in the line is less than max size, then all the string has been added
  IF l_newpos LT gd_max.
    gd_pos = l_newpos.

    " If > max size, pass to a new line to complete the string
  ELSE.
    APPEND gt_data. CLEAR gt_data.

    l_remind = l_newpos - gd_max.
    IF l_remind GE 0.
      l_shift = l_length - l_remind.
      IF l_shift GT 0.
        SHIFT l_value BY l_shift PLACES.
      ENDIF.
    ENDIF.

    gt_data(gd_max) = l_value.
    gd_pos = l_remind.
  ENDIF.
ENDFORM.                    "fill_data


*&---------------------------------------------------------------------*
*&      Form  process_xml_length
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->P_SIZE     text
*----------------------------------------------------------------------*
FORM process_xml_length CHANGING p_size.
  DATA size TYPE i.
  DATA l_xml_last_line_length TYPE i.

  DESCRIBE TABLE gt_data LINES p_size.
  IF p_size > 0.
    READ TABLE gt_data INDEX p_size.
    l_xml_last_line_length = STRLEN( gt_data ).
  ENDIF.

  p_size = ( p_size - 1 ) * gd_max + l_xml_last_line_length.
ENDFORM.                    "process_xml_length

*&---------------------------------------------------------------------*
*&      Form  xml_to_data
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->P_TABLE    text
*----------------------------------------------------------------------*
FORM xml_to_data CHANGING p_struct.
  DATA: l_parser TYPE REF TO zcl_utils_xml_parser,
        l_size TYPE i.

  " Calculate the size of the table
  PERFORM process_xml_length CHANGING l_size.

  " Parse the XML
  IF l_size GT 0.
    CREATE OBJECT l_parser.
    CALL METHOD l_parser->parse_xml_to_data( EXPORTING  p_xml = gt_data[]
                                                        p_size = l_size
                                              CHANGING  p_struct = p_struct ).
  ENDIF.
ENDFORM.                    "xml_to_data

*&---------------------------------------------------------------------*
*&      Form  data_to_xml
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->P_TABLE    text
*----------------------------------------------------------------------*
FORM data_to_xml USING p_struct.
  DATA: l_parser TYPE REF TO zcl_utils_xml_parser.

  " Parse the data
  CREATE OBJECT l_parser.
  CALL METHOD l_parser->parse_data_to_xml( EXPORTING p_struct = p_struct ).
ENDFORM.                    "xml_to_data
Last Updated ( Monday, 10 November 2008 11:43 )