FUNCTION z_xml_to_table.
*"----------------------------------------------------------------------
*"*"Local interface:
*" IMPORTING
*" REFERENCE(IV_XML) TYPE STRING
*" REFERENCE(IV_ROOT_NODE_NAME) TYPE STRING OPTIONAL
*" EXPORTING
*" REFERENCE(E_DATA) TYPE ANY
*"----------------------------------------------------------------------
* XML을 입력받아 인터널 테이블 또는 스트럭처로 변환한다.
* 이름의 경우 XML은 대소문자 구분하지만 ABAP에서는 대문자로 변경하여 처리함.
* 예: <Row><col1>a</col1><col2>B<col2><Row>
* 변환: ROW[1]-COL1 = 'a', ROW[1]-COl2 = 'B'
DATA: lo_ixml TYPE REF TO if_ixml,
lo_stream_factory TYPE REF TO if_ixml_stream_factory,
lo_istream TYPE REF TO if_ixml_istream,
lo_document TYPE REF TO if_ixml_document,
lo_parser TYPE REF TO if_ixml_parser,
lo_node TYPE REF TO if_ixml_node,
lo_node_coll TYPE REF TO if_ixml_node_collection,
lo_node_list TYPE REF TO if_ixml_node_list,
lo_node_iterator TYPE REF TO if_ixml_node_iterator,
lv_flag_to_child TYPE flag.
CHECK: iv_xml IS NOT INITIAL.
lo_ixml = cl_ixml=>create( ).
lo_stream_factory = lo_ixml->create_stream_factory( ).
lo_istream = lo_stream_factory->create_istream_cstring( string = iv_xml ).
lo_document = lo_ixml->create_document( ).
lo_parser = lo_ixml->create_parser(
document = lo_document
istream = lo_istream
stream_factory = lo_stream_factory
).
lo_parser->parse( ).
IF iv_root_node_name IS NOT INITIAL.
" 시작 노드 이름(IV_ROOT_NODE_NAME) 이 있으면
lo_node_coll = lo_document->get_elements_by_tag_name(
name = iv_root_node_name
).
lo_node_iterator = lo_node_coll->create_iterator( ).
lv_flag_to_child = ''.
ELSE.
" 없으면 document 의 children 으로 시작.
lo_node_list = lo_document->get_children( ).
lo_node_iterator = lo_node_list->create_iterator( ).
lv_flag_to_child = 'X'.
ENDIF.
PERFORM xml_to_table_recursion
USING lo_node_iterator
lv_flag_to_child
CHANGING e_data.
ENDFUNCTION.
*&---------------------------------------------------------------------*
*& Form xml_to_table_recursion
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* -->IO_NODE_ITERATOR text
* -->IV_FLAG_TO_CHILD text
* <--C_DATA text
*----------------------------------------------------------------------*
FORM xml_to_table_recursion USING io_node_iterator TYPE REF TO if_ixml_node_iterator
iv_flag_to_child TYPE flag
CHANGING c_data TYPE any.
DATA: lo_node TYPE REF TO if_ixml_node,
lo_node_coll TYPE REF TO if_ixml_node_collection,
lo_node_list TYPE REF TO if_ixml_node_list,
lo_node_attrs TYPE REF TO if_ixml_named_node_map,
lo_node_iterator TYPE REF TO if_ixml_node_iterator,
lv_c_data_type TYPE c,
lv_node_type TYPE i,
lv_node_name TYPE string,
lv_node_value TYPE string.
FIELD-SYMBOLS: <lt_data> TYPE table,
<ls_data> TYPE data,
<l_data> TYPE data.
DESCRIBE FIELD c_data TYPE lv_c_data_type.
IF lv_c_data_type EQ 'h'. " h : Internal table , u v : structure
" 인터널 테이블 이면 빈줄 하나 추가하여 진행한다.
ASSIGN c_data TO <lt_data>.
APPEND INITIAL LINE TO <lt_data> ASSIGNING <ls_data>.
ELSE.
ASSIGN c_data TO <ls_data>.
ENDIF.
DO.
lo_node = io_node_iterator->get_next( ).
IF lo_node IS INITIAL.
EXIT.
ENDIF.
lv_node_type = lo_node->get_type( ).
CASE lv_node_type.
WHEN if_ixml_node=>co_node_element.
" 노드 엘리먼트
lv_node_name = lo_node->get_name( ).
TRANSLATE lv_node_name TO UPPER CASE. " 노드 이름을 대문자로
IF iv_flag_to_child IS NOT INITIAL. " true
ASSIGN COMPONENT lv_node_name OF STRUCTURE <ls_data> TO <l_data>.
CHECK: sy-subrc EQ 0. " 이름이 일치하는 필드가 없으면 무시.
ELSE.
ASSIGN <ls_data> TO <l_data>.
ENDIF.
" 자식 노드
lo_node_list = lo_node->get_children( ).
IF lo_node_list->get_length( ) > 0.
lo_node_iterator = lo_node_list->create_iterator( ).
PERFORM xml_to_table_recursion
USING lo_node_iterator
'X'
CHANGING <l_data>.
ENDIF.
" 어트리뷰트
lo_node_attrs = lo_node->get_attributes( ).
IF lo_node_attrs->get_length( ) > 0.
lo_node_iterator = lo_node_attrs->create_iterator( ).
PERFORM xml_to_table_recursion
USING lo_node_iterator
'X'
CHANGING <l_data>.
ENDIF.
WHEN if_ixml_node=>co_node_text OR if_ixml_node=>co_node_cdata_section.
" 텍스트 값
lv_node_value = lo_node->get_value( ).
<ls_data> = lv_node_value.
WHEN if_ixml_node=>co_node_attribute.
" 노드 어트리뷰트
lv_node_name = lo_node->get_name( ).
TRANSLATE lv_node_name TO UPPER CASE. " 노드 이름을 대문자로
ASSIGN COMPONENT lv_node_name OF STRUCTURE <ls_data> TO <l_data>.
CHECK: sy-subrc EQ 0. " 이름이 일치하는 필드가 없으면 무시.
lv_node_value = lo_node->get_value( ).
<l_data> = lv_node_value.
WHEN OTHERS.
" 기타: 무시
ENDCASE.
ENDDO.
ENDFORM. " XML_TO_TABLE_RECURSION
*"----------------------------------------------------------------------
*"*"Local interface:
*" IMPORTING
*" REFERENCE(IV_XML) TYPE STRING
*" REFERENCE(IV_ROOT_NODE_NAME) TYPE STRING OPTIONAL
*" EXPORTING
*" REFERENCE(E_DATA) TYPE ANY
*"----------------------------------------------------------------------
* XML을 입력받아 인터널 테이블 또는 스트럭처로 변환한다.
* 이름의 경우 XML은 대소문자 구분하지만 ABAP에서는 대문자로 변경하여 처리함.
* 예: <Row><col1>a</col1><col2>B<col2><Row>
* 변환: ROW[1]-COL1 = 'a', ROW[1]-COl2 = 'B'
DATA: lo_ixml TYPE REF TO if_ixml,
lo_stream_factory TYPE REF TO if_ixml_stream_factory,
lo_istream TYPE REF TO if_ixml_istream,
lo_document TYPE REF TO if_ixml_document,
lo_parser TYPE REF TO if_ixml_parser,
lo_node TYPE REF TO if_ixml_node,
lo_node_coll TYPE REF TO if_ixml_node_collection,
lo_node_list TYPE REF TO if_ixml_node_list,
lo_node_iterator TYPE REF TO if_ixml_node_iterator,
lv_flag_to_child TYPE flag.
CHECK: iv_xml IS NOT INITIAL.
lo_ixml = cl_ixml=>create( ).
lo_stream_factory = lo_ixml->create_stream_factory( ).
lo_istream = lo_stream_factory->create_istream_cstring( string = iv_xml ).
lo_document = lo_ixml->create_document( ).
lo_parser = lo_ixml->create_parser(
document = lo_document
istream = lo_istream
stream_factory = lo_stream_factory
).
lo_parser->parse( ).
IF iv_root_node_name IS NOT INITIAL.
" 시작 노드 이름(IV_ROOT_NODE_NAME) 이 있으면
lo_node_coll = lo_document->get_elements_by_tag_name(
name = iv_root_node_name
).
lo_node_iterator = lo_node_coll->create_iterator( ).
lv_flag_to_child = ''.
ELSE.
" 없으면 document 의 children 으로 시작.
lo_node_list = lo_document->get_children( ).
lo_node_iterator = lo_node_list->create_iterator( ).
lv_flag_to_child = 'X'.
ENDIF.
PERFORM xml_to_table_recursion
USING lo_node_iterator
lv_flag_to_child
CHANGING e_data.
ENDFUNCTION.
*&---------------------------------------------------------------------*
*& Form xml_to_table_recursion
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* -->IO_NODE_ITERATOR text
* -->IV_FLAG_TO_CHILD text
* <--C_DATA text
*----------------------------------------------------------------------*
FORM xml_to_table_recursion USING io_node_iterator TYPE REF TO if_ixml_node_iterator
iv_flag_to_child TYPE flag
CHANGING c_data TYPE any.
DATA: lo_node TYPE REF TO if_ixml_node,
lo_node_coll TYPE REF TO if_ixml_node_collection,
lo_node_list TYPE REF TO if_ixml_node_list,
lo_node_attrs TYPE REF TO if_ixml_named_node_map,
lo_node_iterator TYPE REF TO if_ixml_node_iterator,
lv_c_data_type TYPE c,
lv_node_type TYPE i,
lv_node_name TYPE string,
lv_node_value TYPE string.
FIELD-SYMBOLS: <lt_data> TYPE table,
<ls_data> TYPE data,
<l_data> TYPE data.
DESCRIBE FIELD c_data TYPE lv_c_data_type.
IF lv_c_data_type EQ 'h'. " h : Internal table , u v : structure
" 인터널 테이블 이면 빈줄 하나 추가하여 진행한다.
ASSIGN c_data TO <lt_data>.
APPEND INITIAL LINE TO <lt_data> ASSIGNING <ls_data>.
ELSE.
ASSIGN c_data TO <ls_data>.
ENDIF.
DO.
lo_node = io_node_iterator->get_next( ).
IF lo_node IS INITIAL.
EXIT.
ENDIF.
lv_node_type = lo_node->get_type( ).
CASE lv_node_type.
WHEN if_ixml_node=>co_node_element.
" 노드 엘리먼트
lv_node_name = lo_node->get_name( ).
TRANSLATE lv_node_name TO UPPER CASE. " 노드 이름을 대문자로
IF iv_flag_to_child IS NOT INITIAL. " true
ASSIGN COMPONENT lv_node_name OF STRUCTURE <ls_data> TO <l_data>.
CHECK: sy-subrc EQ 0. " 이름이 일치하는 필드가 없으면 무시.
ELSE.
ASSIGN <ls_data> TO <l_data>.
ENDIF.
" 자식 노드
lo_node_list = lo_node->get_children( ).
IF lo_node_list->get_length( ) > 0.
lo_node_iterator = lo_node_list->create_iterator( ).
PERFORM xml_to_table_recursion
USING lo_node_iterator
'X'
CHANGING <l_data>.
ENDIF.
" 어트리뷰트
lo_node_attrs = lo_node->get_attributes( ).
IF lo_node_attrs->get_length( ) > 0.
lo_node_iterator = lo_node_attrs->create_iterator( ).
PERFORM xml_to_table_recursion
USING lo_node_iterator
'X'
CHANGING <l_data>.
ENDIF.
WHEN if_ixml_node=>co_node_text OR if_ixml_node=>co_node_cdata_section.
" 텍스트 값
lv_node_value = lo_node->get_value( ).
<ls_data> = lv_node_value.
WHEN if_ixml_node=>co_node_attribute.
" 노드 어트리뷰트
lv_node_name = lo_node->get_name( ).
TRANSLATE lv_node_name TO UPPER CASE. " 노드 이름을 대문자로
ASSIGN COMPONENT lv_node_name OF STRUCTURE <ls_data> TO <l_data>.
CHECK: sy-subrc EQ 0. " 이름이 일치하는 필드가 없으면 무시.
lv_node_value = lo_node->get_value( ).
<l_data> = lv_node_value.
WHEN OTHERS.
" 기타: 무시
ENDCASE.
ENDDO.
ENDFORM. " XML_TO_TABLE_RECURSION
트랜스포매이션 사용도 있는듯 합니다.
https://archive.sap.com/discussions/thread/1204513
제가 사용한 소스도 있는데 나중에 저도 올려볼게요~
좋은 정보 감사합니다^^