IT WORK/SAP FI and ABAP
[ABAP] XML to JSON
Bathildis
2024. 3. 20. 14:44
반응형
*&---------------------------------------------------------------------*
*& Report YXMLTOJSON
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*
REPORT YXMLTOJSON.
SELECTION-SCREEN: BEGIN OF BLOCK B2 WITH FRAME.
PARAMETERS : P_FILE LIKE RLGRAP-FILENAME OBLIGATORY.
SELECTION-SCREEN: END OF BLOCK B2.
*Select the file from the Local system
AT SELECTION-SCREEN ON VALUE-REQUEST FOR P_FILE.
DATA: DIRECTORY TYPE STRING,
FILETABLE TYPE FILETABLE,
LINE TYPE LINE OF FILETABLE,
RC TYPE I.
CALL METHOD CL_GUI_FRONTEND_SERVICES=>GET_TEMP_DIRECTORY
CHANGING
TEMP_DIR = DIRECTORY.
CALL METHOD CL_GUI_FRONTEND_SERVICES=>FILE_OPEN_DIALOG
EXPORTING
WINDOW_TITLE = 'SELECT THE FILE'
INITIAL_DIRECTORY = DIRECTORY
FILE_FILTER = '*.xml'
MULTISELECTION = ' '
CHANGING
FILE_TABLE = FILETABLE
RC = RC.
IF RC = 1.
READ TABLE FILETABLE INDEX 1 INTO LINE.
P_FILE = LINE-FILENAME.
ENDIF.
START-OF-SELECTION.
DATA : BEGIN OF XMLTAB OCCURS 0,
f(255) TYPE C,
END OF XMLTAB.
DATA : XMLSTR TYPE STRING.
DATA : LV_PATH TYPE STRING.
LV_PATH = P_FILE.
CALL FUNCTION 'GUI_UPLOAD'
EXPORTING
FILENAME = LV_PATH
FILETYPE = 'ASC'
TABLES
DATA_TAB = XMLTAB.
LOOP AT XMLTAB.
CONCATENATE XMLSTR XMLTAB-F INTO XMLSTR.
ENDLOOP.
TYPES: BEGIN OF NODE,
NODE_TYPE TYPE IF_SXML_NODE=>NODE_TYPE,
NAME TYPE STRING,
VALUE TYPE STRING,
ARRAY TYPE C LENGTH 1,
END OF NODE.
DATA NODES TYPE TABLE OF NODE WITH EMPTY KEY.
DATA(XML_STRING) = XMLSTR.
DATA(XML) = CL_ABAP_CODEPAGE=>CONVERT_TO(
REPLACE( VAL = XML_STRING SUB = |\n| WITH = `` OCC = 0 ) ).
DATA(OUT) = CL_DEMO_OUTPUT=>NEW( )->BEGIN_SECTION( `XML-Data` )->WRITE_XML( XML ).
"Parsing XML into an internal table
DATA(READER) = CL_SXML_STRING_READER=>CREATE( XML ).
CLEAR NODES.
TRY.
DO.
READER->NEXT_NODE( ).
IF READER->NODE_TYPE = IF_SXML_NODE=>CO_NT_FINAL.
EXIT.
ENDIF.
APPEND VALUE #(
NODE_TYPE = READER->NODE_TYPE
NAME = READER->PREFIX &&
COND STRING(
WHEN READER->PREFIX IS NOT INITIAL
THEN `:` ) && READER->NAME
VALUE = READER->VALUE ) TO NODES.
IF READER->NODE_TYPE = IF_SXML_NODE=>CO_NT_ELEMENT_OPEN.
DO.
READER->NEXT_ATTRIBUTE( ).
IF READER->NODE_TYPE <> IF_SXML_NODE=>CO_NT_ATTRIBUTE.
EXIT.
ENDIF.
APPEND VALUE #(
NODE_TYPE = IF_SXML_NODE=>CO_NT_INITIAL
NAME = READER->PREFIX &&
COND STRING(
WHEN READER->PREFIX IS NOT INITIAL
THEN `:` ) && READER->NAME
VALUE = READER->VALUE ) TO NODES.
ENDDO.
ENDIF.
ENDDO.
CATCH CX_SXML_PARSE_ERROR INTO DATA(PARSE_ERROR).
OUT->WRITE_TEXT( PARSE_ERROR->GET_TEXT( ) ).
ENDTRY.
"Determine the array limits in the internal table
LOOP AT NODES ASSIGNING FIELD-SYMBOL(<NODE_OPEN>)
WHERE
NODE_TYPE = IF_SXML_NODE=>CO_NT_ELEMENT_OPEN
AND ARRAY IS INITIAL.
DATA(IDX_OPEN) = SY-TABIX.
LOOP AT NODES ASSIGNING FIELD-SYMBOL(<NODE_CLOSE>)
FROM IDX_OPEN + 1
WHERE
NODE_TYPE = IF_SXML_NODE=>CO_NT_ELEMENT_CLOSE
AND NAME = <NODE_OPEN>-NAME.
DATA(IDX_CLOSE) = SY-TABIX.
IF IDX_CLOSE < LINES( NODES ).
ASSIGN NODES[ IDX_CLOSE + 1 ] TO FIELD-SYMBOL(<NODE>).
IF <NODE>-NODE_TYPE = IF_SXML_NODE=>CO_NT_ELEMENT_OPEN AND
<NODE>-NAME = <NODE_OPEN>-NAME.
<NODE_OPEN>-ARRAY = 'O'.
<NODE>-ARRAY = '_'.
ELSEIF
( <NODE>-NODE_TYPE = IF_SXML_NODE=>CO_NT_ELEMENT_OPEN
AND <NODE>-NAME <> <NODE_OPEN>-NAME )
OR <NODE>-NODE_TYPE = IF_SXML_NODE=>CO_NT_ELEMENT_CLOSE.
<NODE_CLOSE>-ARRAY = COND #(
WHEN <NODE_OPEN>-ARRAY = 'O' THEN 'C' ).
EXIT.
ENDIF.
ENDIF.
ENDLOOP.
ENDLOOP.
"out->begin_section( `Nodes`
")->write( nodes ).
"Render the internal table to JSON-XML
DATA(WRITER) = CAST IF_SXML_WRITER(
CL_SXML_STRING_WRITER=>CREATE( TYPE = IF_SXML=>CO_XT_JSON ) ).
"create( type = if_sxml=>co_xt_xml10 ) ).
TRY.
WRITER->OPEN_ELEMENT( NAME = 'object' ).
LOOP AT NODES ASSIGNING <NODE>.
CASE <NODE>-NODE_TYPE.
WHEN IF_SXML_NODE=>CO_NT_ELEMENT_OPEN.
IF <NODE>-ARRAY IS INITIAL.
WRITER->OPEN_ELEMENT( NAME = 'object' ).
WRITER->WRITE_ATTRIBUTE( NAME = 'name'
VALUE = <NODE>-NAME ).
ELSEIF <NODE>-ARRAY = 'O'.
WRITER->OPEN_ELEMENT( NAME = 'array' ).
WRITER->WRITE_ATTRIBUTE( NAME = 'name'
VALUE = <NODE>-NAME ).
WRITER->OPEN_ELEMENT( NAME = 'object' ).
ELSEIF <NODE>-ARRAY = '_'.
WRITER->OPEN_ELEMENT( NAME = 'object' ).
ENDIF.
WHEN IF_SXML_NODE=>CO_NT_ELEMENT_CLOSE.
IF <NODE>-ARRAY <> 'C'.
WRITER->CLOSE_ELEMENT( ).
ELSE.
WRITER->CLOSE_ELEMENT( ).
WRITER->CLOSE_ELEMENT( ).
ENDIF.
WHEN IF_SXML_NODE=>CO_NT_INITIAL.
WRITER->OPEN_ELEMENT( NAME = 'str' ).
WRITER->WRITE_ATTRIBUTE( NAME = 'name'
VALUE = `a_` && <NODE>-NAME ).
WRITER->WRITE_VALUE( <NODE>-VALUE ).
WRITER->CLOSE_ELEMENT( ).
WHEN IF_SXML_NODE=>CO_NT_VALUE.
WRITER->OPEN_ELEMENT( NAME = 'str' ).
WRITER->WRITE_ATTRIBUTE( NAME = 'name'
VALUE = `e_` && <NODE>-NAME ).
WRITER->WRITE_VALUE( <NODE>-VALUE ).
WRITER->CLOSE_ELEMENT( ).
WHEN OTHERS.
OUT->DISPLAY( 'A node type is not yet supported' ).
RETURN.
ENDCASE.
ENDLOOP.
WRITER->CLOSE_ELEMENT( ).
DATA(JSON) =
CAST CL_SXML_STRING_WRITER( WRITER )->GET_OUTPUT( ).
OUT->NEXT_SECTION( 'JSON-Data' ).
IF WRITER->IF_SXML~TYPE = IF_SXML=>CO_XT_JSON.
OUT->WRITE_JSON( JSON ).
ELSEIF WRITER->IF_SXML~TYPE = IF_SXML=>CO_XT_XML10.
OUT->WRITE_XML( JSON ).
ENDIF.
CATCH CX_SXML_ERROR INTO DATA(EXC).
OUT->WRITE( EXC->GET_TEXT( ) ).
ENDTRY.
OUT->DISPLAY( ).
반응형