做接口 XML 和 JSON 的选择以及处理 XML 的几个函数

作者:ABAP老白 约 6 分钟阅读 更新日期:2025-03-02 1 年前更新 标签:ABAP, 开发
做接口 XML 和 JSON 的选择以及处理 XML 的几个函数 - 封面图
做接口 XML 和 JSON 的选择以及处理 XML 的几个函数 - 封面图

ABAP和外部系统做接口的时候,XML和JSON是两种常用的数据传输格式,它们各自有一些优缺点,如下所述:

XML:

优点:XML具有较好的可扩展性和灵活性,可以通过定义DTD或XSD等文档类型定义来定义和验证数据结构。XML的标记语言具有很强的可读性,易于人们理解和处理,对于需要手动编辑的文件而言,这是一个重要的优势。

缺点:XML语法比JSON复杂,需要更多的字符和标签来表示相同的信息,这导致XML的文件大小较大。在处理大型数据时,会带来较高的处理负载和内存占用。与JSON相比,XML处理速度较慢。

JSON:

优点:JSON比XML更轻量级,因此在传输和处理大量数据时更有效率。语法简单,易于阅读和编写,并且可以通过各种编程语言和平台进行处理。

缺点:JSON缺乏XML的严格数据类型,无法通过DTD或XSD等文档类型定义来验证数据结构的正确性。不支持注释,这使得JSON文件不像XML那样容易被人类读取和编辑,对于需要手动编辑的文件而言,JSON的可读性不如XML。

实事求是的讲,就ABAP做的接口而言,大多都是固定的数据格式,不需要人工解读,DTD和XSD在接口使用场景下更是毫无用处,所以XML的优点在这儿无任何卵用,反而是文件大、效率低、处理起来恶心,相比JSON一无是处。

**所以建议使用JSON来代替XML。**

正是因为XML处理起来太麻烦,所以给大家提供几个有用的函数,有了这几个函数足矣应付90+%的XML格式接口场景了。

1、SAP数据转为XML文件

FUNCTION zxml_data_to_string .*"----------------------------------------------------------------------*"*"局部接口:*" IMPORTING*" REFERENCE(DATA) TYPE ANY*" REFERENCE(CASE) TYPE C OPTIONAL*" REFERENCE(PRETTY) TYPE C OPTIONAL*" REFERENCE(ROOTNAME) TYPE STRING DEFAULT 'BOOT'*" REFERENCE(CHARACTER_SET) TYPE STRING DEFAULT 'UTF-8'*" REFERENCE(DCXMLINIT) TYPE DCXMLINIT DEFAULT 'N'*" EXPORTING*" REFERENCE(XMLSTR) TYPE STRING*" REFERENCE(XMLXSTR) TYPE XSTRING*" TABLES*" MAPTAB STRUCTURE ZXML_NODEN_MAPPING OPTIONAL*" EXCEPTIONS*" DATA_TO_DOM_ERROR*"---------------------------------------------------------------------- DATA ifxml TYPE REF TO if_ixml. DATA factory TYPE REF TO if_ixml_stream_factory. DATA document TYPE REF TO if_ixml_document. DATA node TYPE REF TO if_ixml_node. DATA iterator TYPE REF TO if_ixml_node_iterator. DATA ostream TYPE REF TO if_ixml_ostream. DATA encoding TYPE REF TO if_ixml_encoding . DATA element TYPE REF TO if_ixml_element. DATA retval TYPE i. DATA str TYPE string. DATA control TYPE dcxmlsercl.

ifxml = cl_ixml=>create( ). document = ifxml->create_document( ). factory = ifxml->create_stream_factory( ). encoding = ifxml->create_encoding( byte_order = 0 character_set = character_set ).

control-init_treat = dcxmlinit .

CALL FUNCTION 'SDIXML_DATA_TO_DOM' EXPORTING name = rootname dataobject = data control = control IMPORTING data_as_dom = element CHANGING document = document EXCEPTIONS illegal_name = 1 OTHERS = 2. IF element IS INITIAL. RAISE data_to_dom_error. ELSE. retval = document->append_child( new_child = element ). ENDIF.
IF case <> '' OR maptab[] IS NOT INITIAL. iterator = document->create_iterator( ). DO. node = iterator->get_next( ). IF node IS INITIAL. EXIT. ENDIF. IF node->get_type( ) = if_ixml_node=>co_node_element. READ TABLE maptab WITH KEY frstr = node->get_name( ). IF sy-subrc = 0. str = maptab-tostr. node->set_name( str ). ELSE. CASE case. WHEN 'U'. node->set_name( to_upper( node->get_name( ) ) ). WHEN 'L'. node->set_name( to_lower( node->get_name( ) ) ). WHEN OTHERS. ENDCASE. ENDIF. ENDIF. ENDDO. ENDIF.

ostream = factory->create_ostream_xstring( string = xmlxstr ). ostream->set_encoding( encoding = encoding ). ostream->set_pretty_print( pretty_print = pretty ). document->render( ostream = ostream ). xmlstr = cl_abap_codepage=>convert_from( source = xmlxstr codepage = character_set ).

ENDFUNCTION.

2、XML转为SAP数据

FUNCTION zxml_string_to_data .*"----------------------------------------------------------------------*"*"局部接口:*" IMPORTING*" REFERENCE(XMLSTR) TYPE STRING*" REFERENCE(ICDATA) TYPE CHAR1 OPTIONAL*" EXPORTING*" REFERENCE(DATA) TYPE ANY*" REFERENCE(SUBRC) TYPE SY-SUBRC*"----------------------------------------------------------------------***如果要取CDATA数据***程序:LSDIXMLF04,FORM get_cdata,做如下修改:* ...* DATA: icdata.** CLEAR value.* IMPORT icdata FROM MEMORY ID 'ZXML_STRING_TO_DATA_ICDATA'.* IF icdata IS NOT INITIAL .* filter = element->create_filter_node_type( 48 ).* ELSE.* filter = element->create_filter_node_type(* if_ixml_node=>co_node_text ).* ENDIF.* iterator = element->create_iterator( 1 ).* ... DATA: go_xml TYPE REF TO cl_xml_document . IF icdata IS NOT INITIAL. EXPORT icdata TO MEMORY ID 'ZXML_STRING_TO_DATA_ICDATA'. "LSDIXMLF04 ENDIF. IF go_xml IS INITIAL. CREATE OBJECT go_xml. ENDIF. CALL METHOD go_xml->parse_string EXPORTING stream = xmlstr RECEIVING retcode = subrc. CALL METHOD go_xml->get_data IMPORTING retcode = subrc CHANGING dataobject = data.

FREE MEMORY ID 'ZXML_STRING_TO_DATA_ICDATA'.ENDFUNCTION.

3、对XML重新处理,比如标签名的批量更改、字符集的转换等

FUNCTION zxml_string_rebuild .*"----------------------------------------------------------------------*"*"局部接口:*" IMPORTING*" REFERENCE(XMLIN) TYPE STRING*" REFERENCE(CASE) TYPE C OPTIONAL*" REFERENCE(PRETTY) TYPE C OPTIONAL*" REFERENCE(CHARACTER_SET) TYPE STRING DEFAULT 'UTF-8'*" EXPORTING*" VALUE(XMLOUT) TYPE STRING*" VALUE(XMLOUTX) TYPE XSTRING*" VALUE(CDATA) TYPE RSTT_T_STRINGS*" TABLES*" MAPTAB STRUCTURE ZXML_NODEN_MAPPING OPTIONAL*" EXCEPTIONS*" XML_ERROR*"----------------------------------------------------------------------

DATA ifxml TYPE REF TO if_ixml. DATA factory TYPE REF TO if_ixml_stream_factory. DATA document TYPE REF TO if_ixml_document. DATA iterator TYPE REF TO if_ixml_node_iterator. DATA node TYPE REF TO if_ixml_node. DATA parser TYPE REF TO if_ixml_parser. DATA istream TYPE REF TO if_ixml_istream. DATA ostream TYPE REF TO if_ixml_ostream. DATA encoding TYPE REF TO if_ixml_encoding .* DATA retval TYPE i. DATA xmlxstr TYPE xstring. DATA str TYPE string. DATA wa_cdata TYPE rstt_s_string.

ifxml = cl_ixml=>create( ). document = ifxml->create_document( ). factory = ifxml->create_stream_factory( ).

xmlxstr = cl_abap_codepage=>convert_to( source = xmlin ). istream = factory->create_istream_xstring( string = xmlxstr ). parser = ifxml->create_parser( document = document stream_factory = factory istream = istream ). IF parser->parse( ) <> 0. RAISE xml_error. ENDIF.

iterator = document->create_iterator( ). DO. node = iterator->get_next( ). IF node IS INITIAL. EXIT. ENDIF.

IF node->get_type( ) = if_ixml_node=>co_node_element. READ TABLE maptab WITH KEY frstr = node->get_name( ). IF sy-subrc = 0. str = maptab-tostr. node->set_name( str ). ELSE. CASE case. WHEN 'U'. node->set_name( to_upper( node->get_name( ) ) ). WHEN 'L'. node->set_name( to_lower( node->get_name( ) ) ). ENDCASE. ENDIF. ELSEIF node->get_type( ) = if_ixml_node=>co_node_cdata_section. wa_cdata-string = node->get_value( ). APPEND wa_cdata TO cdata. ENDIF. ENDDO.

ostream = factory->create_ostream_xstring( string = xmloutx ).

IF character_set IS NOT INITIAL. encoding = ifxml->create_encoding( byte_order = 0 character_set = character_set ). ostream->set_encoding( encoding = encoding ). ENDIF. IF pretty IS NOT INITIAL. ostream->set_pretty_print( pretty_print = pretty ). ENDIF.

document->render( ostream = ostream ).  xmlout = cl_abap_codepage=>convert_from( xmloutx ).ENDFUNCTION.

4、XML表示数组(内表)有两种格式,分别是

做接口 XML 和 JSON 的选择以及处理 XML 的几个函数 - 封面图
做接口 XML 和 JSON 的选择以及处理 XML 的几个函数 - 封面图

和:

做接口 XML 和 JSON 的选择以及处理 XML 的几个函数 - 封面图
做接口 XML 和 JSON 的选择以及处理 XML 的几个函数 - 封面图

SAP默认生成是第二种格式,但是如果外部系统只认第一种格式呢?

这个时候就需要有把两个格式相互转换的方法,也就是下面两个函数:

FUNCTION ZXML_TRANSFER_ITEMTAG1 .*"----------------------------------------------------------------------*"*"局部接口:*" IMPORTING*" VALUE(XMLIN) TYPE STRING*" EXPORTING*" VALUE(XMLSTR) TYPE STRING*" TABLES*" TAGTAB*"---------------------------------------------------------------------- DATA: maptab TYPE TABLE OF zxml_noden_mapping WITH HEADER LINE. DATA: tagc(100). DATA: moff TYPE i .

CHECK xmlin IS NOT INITIAL. FIND FIRST OCCURRENCE OF '<item>' IN xmlin . IF sy-subrc = 0. MESSAG

...

ABAP老白

关于作者:ABAP老白

企业信息化与 SAP 技术顾问,长期专注 SAP ABAP、FI/CO、MM、SD 等模块的技术分享与实战经验总结。查看更多介绍

来源说明:本文内容由「做接口XML和JSON的选择以及处理XML的几个函数.md」整理生成,仅用于内部技术分享与学习交流。