*&---------------------------------------------------------------------*
*& 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



