REPORT zpj_xml_create.

TYPE-POOLS: ixml.
CLASS cl_ixml DEFINITION LOAD.

TYPES: BEGIN OF t_xml_line,
        data(256) TYPE x,
       END OF t_xml_line.

DATA: g_ixml            TYPE REF TO if_ixml,
      g_streamfactory   TYPE REF TO if_ixml_stream_factory,
      g_ostream         TYPE REF TO if_ixml_ostream,
      g_renderer        TYPE REF TO if_ixml_renderer,
      g_document        TYPE REF TO if_ixml_document.

DATA: g_element_flights TYPE REF TO if_ixml_element,
      g_element_airline TYPE REF TO if_ixml_element,
      g_element_flight  TYPE REF TO if_ixml_element,
      g_element_from    TYPE REF TO if_ixml_element,
      g_element_to      TYPE REF TO if_ixml_element,
      g_element_dummy   TYPE REF TO if_ixml_element,
      g_value           TYPE string,
      g_carrname           TYPE scarr-carrname.

DATA: g_xml_table       TYPE TABLE OF t_xml_line,
      g_xml_size        TYPE i,
      g_rc              TYPE i,
      g_rcode           TYPE c.
DATA: g_filename        TYPE string.

DATA: gt_spfli          TYPE TABLE OF spfli.
DATA: g_spfli           TYPE spfli.

****************************************
* screen selection                     *
****************************************
SELECTION-SCREEN: BEGIN OF BLOCK b0 WITH FRAME TITLE text-000.
SELECTION-SCREEN: BEGIN OF BLOCK b2 WITH FRAME TITLE text-002.
PARAMETERS: p_input LIKE rlgrap-filename DEFAULT 'C:\temp\flights.xml'.
SELECTION-SCREEN: END OF BLOCK b2.
PARAMETERS: p_indent AS CHECKBOX DEFAULT 'X'.
SELECTION-SCREEN: END OF BLOCK b0.

AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_input.
  PERFORM get_file_name USING ',*.XML.' CHANGING p_input.

****************************************
* START OF SELECTION                   *
****************************************
START-OF-SELECTION.
*   Fill the internal table
  SELECT * FROM spfli INTO TABLE gt_spfli.

*   Sort internal table
  SORT gt_spfli BY carrid.

*   Start filling xml dom object from internal table
  LOOP AT gt_spfli INTO g_spfli.

    AT FIRST.
*       Creating a ixml factory
      g_ixml = cl_ixml=>create( ).
*       Creating the dom object model
      g_document = g_ixml->create_document( ).
*       Fill root node with value flights
      g_element_flights  = g_document->create_simple_element(
                  name = 'flights'
                  parent = g_document ).
    ENDAT.

    AT NEW carrid.
*       Create element 'airline' as child of 'flights'
      g_element_airline  = g_document->create_simple_element(
                  name = 'airline'
                  parent = g_element_flights  ).

*       Create attribute 'code' of node 'airline'
      g_value = g_spfli-carrid.
      g_rc = g_element_airline->set_attribute( name = 'code'
       value = g_value ).

*       Create attribute 'name' of node 'airline'
      SELECT SINGLE carrname FROM scarr INTO g_carrname WHERE carrid
      EQ g_spfli-carrid.
      g_value = g_carrname.
      g_rc = g_element_airline->set_attribute( name = 'name'
      value = g_value ).

    ENDAT.

    AT NEW connid.
*       Create element 'flight' as child of 'airline'
      g_element_flight  = g_document->create_simple_element(
                  name = 'flight'
                  parent = g_element_airline  ).

*       Create attribute 'number' of node 'flight'
      g_value = g_spfli-connid.
      g_rc = g_element_flight->set_attribute( name = 'number'
                                            value = g_value ).

    ENDAT.

*     Create element 'from' as child of 'flight'
    CONCATENATE g_spfli-cityfrom ',' g_spfli-countryfr INTO g_value.
    g_element_from  = g_document->create_simple_element(
                name = 'from'
                value = g_value
                parent = g_element_flight  ).

*     Create attribute 'airport' of node 'from'
    g_value = g_spfli-airpfrom.
    g_rc = g_element_from->set_attribute( name = 'airport'
    value = g_value ).

*     Create element 'to' as child of 'flight'
    CONCATENATE g_spfli-cityto ',' g_spfli-countryto INTO g_value.
    g_element_to  = g_document->create_simple_element(
                name = 'to'
                value = g_value
                parent = g_element_flight  ).

*     Create attribute 'airport' of node 'from'
    g_value = g_spfli-airpto.
    g_rc = g_element_to->set_attribute( name = 'airport'
    value = g_value ).

*     Create element 'departure' as child of 'flight'
    g_value = g_spfli-deptime.
    g_element_dummy  = g_document->create_simple_element(
                name = 'departure'
                value = g_value
                parent = g_element_flight ).

*     Create element 'arrival' as child of 'flight'
    g_value = g_spfli-arrtime.
    g_element_dummy  = g_document->create_simple_element(
                name = 'arrival'
                value = g_value
                parent = g_element_flight ).

*     Create element 'type' as child of 'flight'
    CASE g_spfli-fltype.
      WHEN 'X'.
        g_value = 'Charter'.
      WHEN OTHERS.
        g_value = 'Scheduled'.
    ENDCASE.
    g_element_dummy  = g_document->create_simple_element(
                name = 'type'
                value = g_value
                parent = g_element_flight ).
  ENDLOOP.

  CHECK sy-subrc = 0.

*   Creating a stream factory
  g_streamfactory = g_ixml->create_stream_factory( ).
*   Connect internal XML table to stream factory
  g_ostream = g_streamfactory->create_ostream_itable(
  table = g_xml_table ).

*   Rendering the document
  g_renderer = g_ixml->create_renderer( ostream  = g_ostream
                                        document = g_document ).

  IF p_indent = 'X'.
    g_rcode = g_renderer->set_normalizing( 'X' ).
  ENDIF.

  g_rc = g_renderer->render( ).

  g_xml_size = g_ostream->get_num_written_raw( ).

  IF p_indent = 'X'.
    PERFORM indent_xml_syntax CHANGING g_xml_table
                                       g_xml_size.
  ENDIF.

*   Saving the XML document
  g_filename = p_input.

  CALL METHOD cl_gui_frontend_services=>gui_download
    EXPORTING
      bin_filesize = g_xml_size
      filename     = g_filename
      filetype     = 'BIN'
    CHANGING
      data_tab     = g_xml_table
    EXCEPTIONS
      OTHERS       = 24.
  IF sy-subrc <> 0.
    MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
               WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
  ENDIF.

*---------------------------------------------------------------------*
*       FORM indent_xml_syntax                                        *
*---------------------------------------------------------------------*
FORM indent_xml_syntax CHANGING pt_xml LIKE g_xml_table
                                p_size LIKE g_xml_size.
  CONSTANTS: c_break(2) TYPE x VALUE '0D0A',
             c_end(1) TYPE x VALUE '0A',
             c_sign(1) TYPE x VALUE '95'.
  TYPES: BEGIN OF t_xml,
          data(500) TYPE x,
         END OF t_xml.
  DATA: ls_xml TYPE t_xml_line,
        lt_xml2 TYPE TABLE OF t_xml,
        ls_xml2 TYPE t_xml.

  LOOP AT pt_xml INTO ls_xml.
    IF ls_xml2 IS INITIAL.
      ls_xml2 = ls_xml.
    ELSE.
      CONCATENATE ls_xml2 ls_xml INTO ls_xml2.
    ENDIF.
    DO.
      REPLACE c_end WITH c_sign INTO ls_xml2.
      IF sy-subrc = 0.
        ADD 1 TO p_size.
      ELSE.
        EXIT.
      ENDIF.
    ENDDO.
    DO.
      REPLACE c_sign WITH c_break INTO ls_xml2.
      IF sy-subrc <> 0.
        EXIT.
      ENDIF.
    ENDDO.
    ls_xml = ls_xml2.
    ls_xml2 = ls_xml2+256.
    APPEND ls_xml TO lt_xml2.
  ENDLOOP.

  pt_xml[] = lt_xml2[].
ENDFORM.

*---------------------------------------------------------------------*
*       FORM get_file_name                                            *
*---------------------------------------------------------------------*
FORM get_file_name USING p_mask
                   CHANGING p_file LIKE rlgrap-filename.
  CALL FUNCTION 'WS_FILENAME_GET'
       EXPORTING
            def_filename     = p_file
            def_path         = 'C:\'
            mask             = p_mask
            mode             = '0'
            title            = ''
       IMPORTING
            filename         = p_file
       EXCEPTIONS
            inv_winsys       = 1
            no_batch         = 2
            selection_cancel = 3
            selection_error  = 4
            OTHERS           = 5.
ENDFORM.