一般CPI到Mapping步骤直接使用RFC的WSDL也可以,通过此方式可以根据RFC的出入参数,导出带item或不带item节点的XSD文件
REPORT yxx_get_xsd.
" XML解析工具
DATA: go_ixml TYPE REF TO if_ixml,
go_streamfactory TYPE REF TO if_ixml_stream_factory,
go_ostream TYPE REF TO if_ixml_ostream,
go_renderer TYPE REF TO if_ixml_renderer,
go_doc TYPE REF TO if_ixml_document,
go_elem TYPE REF TO if_ixml_element,
gt_xml_table TYPE TABLE OF xml_str,
* gt_xml_table TYPE TABLE OF xml_line, " ECC系统使用的是xml_line,到S4已经没有这个结构了
gv_xml_size TYPE i,
gv_value TYPE string.
DATA: gv_path TYPE string,
gv_fullpath TYPE string,
gv_extension TYPE string,
gv_filename TYPE string.
" 字段层级结构
TYPES: BEGIN OF ty_node,
level TYPE i, " 层级
fname TYPE string, " 字段名
ftype TYPE string, " 字段类型
felem TYPE string, " 数据元素
el TYPE REF TO if_ixml_element, " 当前节点XML对象
END OF ty_node.
SELECTION-SCREEN BEGIN OF BLOCK blk01 WITH FRAME TITLE TEXT-101.
PARAMETERS: p_rfc TYPE rs38l-name OBLIGATORY MATCHCODE OBJECT sfunc_modules, " 函数名
p_item AS CHECKBOX. " 是否生成表item节点
SELECTION-SCREEN END OF BLOCK blk01.
START-OF-SELECTION.
" 检查函数名
SELECT SINGLE
funcname
FROM tfdir
WHERE
funcname = @p_rfc
INTO @DATA(ls_tfdir).
IF sy-subrc <> 0.
MESSAGE '函数不存在' TYPE 'E'.
ENDIF.
END-OF-SELECTION.
PERFORM frm_create_xsd USING 'I'.
PERFORM frm_create_xsd USING 'E'.
*&---------------------------------------------------------------------*
*& Form frm_create_xsd
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& --> p1 text
*& <-- p2 text
*&---------------------------------------------------------------------*
FORM frm_create_xsd USING pv_type TYPE c.
DATA: ls_node TYPE ty_node,
lo_root TYPE REF TO if_ixml_element.
" 获取函数参数 出/入参
SELECT
funcname,
pposition,
parameter, " 参数名
paramtype, " 参数类型
structure " 参考的结构
FROM fupararef
WHERE
funcname = @p_rfc AND
paramtype = @pv_type
INTO TABLE @DATA(lt_data).
SORT lt_data BY paramtype pposition..
" 获取函数参数 表
SELECT
funcname,
pposition,
parameter, " 参数名
paramtype, " 参数类型
structure " 参考的结构
FROM fupararef
WHERE
funcname = @p_rfc AND
paramtype = 'T'
INTO TABLE @DATA(lt_data1).
SORT lt_data1 BY paramtype pposition..
APPEND LINES OF lt_data1 TO lt_data.
IF lt_data IS INITIAL.
RETURN.
ENDIF.
go_ixml = cl_ixml=>create( ).
go_doc = go_ixml->create_document( ).
" 构建初始xsd节点schema
go_elem = go_doc->create_simple_element( name = 'schema' parent = go_doc ).
go_elem->set_attribute( name = 'attributeFormDefault' value = 'unqualified' ).
go_elem->set_attribute( name = 'elementFormDefault' value = 'qualified' ).
go_elem->set_attribute( name = 'xmlns' value = 'http://www.w3.org/2001/XMLSchema' ).
ls_node-el = go_elem.
" 构建根节点Request
go_elem = go_doc->create_simple_element( name = 'element' parent = ls_node-el ).
IF pv_type = 'I'.
go_elem->set_attribute( name = 'name' value = 'Request' ).
ELSE.
go_elem->set_attribute( name = 'name' value = 'Respond' ).
ENDIF.
ls_node-el = go_elem.
" 构建XML节点 complexType
go_elem = go_doc->create_simple_element( name = 'complexType' parent = ls_node-el ).
ls_node-el = go_elem.
" 构建XML节点 sequence
go_elem = go_doc->create_simple_element( name = 'sequence' parent = ls_node-el ).
ls_node-el = go_elem.
" 根节点
lo_root = ls_node-el.
" 从顶层节点向下遍历
LOOP AT lt_data INTO DATA(ls_data).
ls_node-level = '1'.
ls_node-fname = ls_data-parameter.
ls_node-felem = ls_data-structure.
ls_node-el = lo_root.
IF ls_data-paramtype = 'T'.
PERFORM frm_expand_node USING ls_node 1 'X'.
ELSE.
PERFORM frm_expand_node USING ls_node 1 ''.
ENDIF.
ENDLOOP.
go_streamfactory = go_ixml->create_stream_factory( ).
go_ostream = go_streamfactory->create_ostream_itable( table = gt_xml_table ).
go_renderer = go_ixml->create_renderer( ostream = go_ostream
document = go_doc ).
go_renderer->render( ).
gv_xml_size = go_ostream->get_num_written_raw( ).
" 选择文件保存路径
IF pv_type = 'I'.
gv_filename = p_rfc && '_Request'.
ELSE.
gv_filename = p_rfc && '_Respond'.
ENDIF.
cl_gui_frontend_services=>file_save_dialog(
EXPORTING
default_extension = 'XSD'
default_file_name = gv_filename
CHANGING
filename = gv_filename
path = gv_path
fullpath = gv_fullpath
EXCEPTIONS
OTHERS = 1 ).
IF sy-subrc <> 0 OR gv_fullpath IS INITIAL.
MESSAGE '未选择文件保存路径' TYPE 'E'. " 未选择文件保存路径
RETURN.
ENDIF.
cl_gui_frontend_services=>gui_download(
EXPORTING
bin_filesize = gv_xml_size
filename = gv_fullpath
filetype = 'BIN'
CHANGING
data_tab = gt_xml_table ).
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_expand_node
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& --> LS_NODE
*& --> LEVEL
*&---------------------------------------------------------------------*
FORM frm_expand_node USING ps_node TYPE ty_node
pv_level TYPE i
pv_table TYPE c.
DATA: ls_node TYPE ty_node,
ls_next TYPE ty_node,
lv_level TYPE i,
lv_table TYPE c.
ls_node = ps_node.
lv_level = pv_level + 1.
IF ls_node-felem CS '-'. " 引用了结构中的元素
ls_node-felem = 'CHAR100'.
ENDIF.
" 检查该节点是否为数据元素,若为数据元素则结束
SELECT SINGLE
rollname
FROM dd04l
WHERE
rollname = @ls_node-felem
INTO @DATA(ls_count).
IF sy-subrc = 0.
ls_node-ftype = 'ELEM'. " 数据元素
go_elem = go_doc->create_simple_element( name = 'element' parent = ls_node-el ).
go_elem->set_attribute( name = 'name' value = ls_node-fname ).
go_elem->set_attribute( name = 'type' value = 'string' ).
go_elem->set_attribute( name = 'minOccurs' value = '0' ).
go_elem->set_attribute( name = 'maxOccurs' value = '1' ).
RETURN.
ENDIF.
" 检查该节点是否为表类型,若为表类型则继续下钻
SELECT SINGLE
typename, " 表类型名称
rowtype " 行类型
FROM dd40l
WHERE
typename = @ls_node-felem
INTO @DATA(ls_dd40l).
IF sy-subrc = 0.
ls_node-ftype = 'TABL'. " 表类型
ELSE.
ls_node-ftype = 'STRU'. " 结构类型
ENDIF.
IF pv_table = 'X'.
ls_node-ftype = 'TABL'. " 表类型
ENDIF.
" 构建XML节点 element
go_elem = go_doc->create_simple_element( name = 'element' parent = ls_node-el ).
go_elem->set_attribute( name = 'name' value = ls_node-fname ).
IF ls_node-ftype = 'TABL' AND p_item IS INITIAL.
go_elem->set_attribute( name = 'minOccurs' value = '0' ).
go_elem->set_attribute( name = 'maxOccurs' value = 'unbounded' ).
ELSE.
go_elem->set_attribute( name = 'minOccurs' value = '0' ).
go_elem->set_attribute( name = 'maxOccurs' value = '1' ).
ENDIF.
ls_node-el = go_elem.
" 构建XML节点 complexType
go_elem = go_doc->create_simple_element( name = 'complexType' parent = ls_node-el ).
ls_node-el = go_elem.
" 构建XML节点 sequence
go_elem = go_doc->create_simple_element( name = 'sequence' parent = ls_node-el ).
ls_node-el = go_elem.
IF p_item = 'X' AND ls_node-ftype = 'TABL'.
" 构建XML节点 element 【item】
go_elem = go_doc->create_simple_element( name = 'element' parent = ls_node-el ).
go_elem->set_attribute( name = 'name' value = 'item' ).
go_elem->set_attribute( name = 'minOccurs' value = '0' ).
go_elem->set_attribute( name = 'maxOccurs' value = 'unbounded' ).
ls_node-el = go_elem.
" 构建XML节点 complexType
go_elem = go_doc->create_simple_element( name = 'complexType' parent = ls_node-el ).
ls_node-el = go_elem.
" 构建XML节点 sequence
go_elem = go_doc->create_simple_element( name = 'sequence' parent = ls_node-el ).
ls_node-el = go_elem.
ENDIF.
IF ls_node-ftype = 'TABL' AND pv_table IS INITIAL.
" 准备下潜展开结构
ls_node-felem = ls_dd40l-rowtype.
ls_node-el = go_elem.
ENDIF.
" 展开结构
SELECT
tabname,
fieldname, " 字段名
rollname, " 数据元素
position " 顺序
FROM dd03l
WHERE
depth = '00' AND " 只要当前层的
fieldname <> '.INCLUDE' AND " 排除include
tabname = @ls_node-felem
INTO TABLE @DATA(lt_dd03l).
SORT lt_dd03l BY position.
LOOP AT lt_dd03l INTO DATA(ls_dd03l).
ls_next-level = lv_level.
ls_next-fname = ls_dd03l-fieldname.
ls_next-felem = ls_dd03l-rollname.
IF ls_next-felem IS INITIAL. " 没有引用数据元素
ls_next-felem = 'CHAR100'.
ENDIF.
ls_next-el = ls_node-el.
PERFORM frm_expand_node USING ls_next lv_level ''.
ENDLOOP.
ENDFORM.