From d2e0ff8abf2812736833d42c487c1089ffd9584c Mon Sep 17 00:00:00 2001 From: danrega <16720986+danrega@users.noreply.github.com> Date: Fri, 15 Mar 2024 16:17:35 +0100 Subject: [PATCH] Update --- src/zcl_demo_abap_aux.clas.abap | 1 + src/zcl_demo_abap_xml_json.clas.abap | 3168 +++++++++++++------------- 2 files changed, 1585 insertions(+), 1584 deletions(-) diff --git a/src/zcl_demo_abap_aux.clas.abap b/src/zcl_demo_abap_aux.clas.abap index dbc8c9d..25a2bcb 100644 --- a/src/zcl_demo_abap_aux.clas.abap +++ b/src/zcl_demo_abap_aux.clas.abap @@ -715,3 +715,4 @@ CLASS zcl_demo_abap_aux IMPLEMENTATION. ENDMETHOD. ENDCLASS. + diff --git a/src/zcl_demo_abap_xml_json.clas.abap b/src/zcl_demo_abap_xml_json.clas.abap index 6ecd7c3..4006f26 100644 --- a/src/zcl_demo_abap_xml_json.clas.abap +++ b/src/zcl_demo_abap_xml_json.clas.abap @@ -1,1585 +1,1585 @@ -*********************************************************************** -* -* ABAP cheat sheet: Working with XML and JSON in ABAP -* -* -------------------------- PURPOSE ---------------------------------- -* - Example that demonstrates working with XML and JSON in ABAP. -* - The following topics are covered:* -* - Processing XML using class libraries (iXML, sXML) -* - XML Transformations using XSLT and Simple Transformations -* - CALL TRANSFORMATION syntax -* - Dealing with JSON data, XCO classes for JSON -* - Excursions: Converting string <-> xstring, compressing and -* decompressing binary data -* -* ----------------------- GETTING STARTED ----------------------------- -* - Open the class with the ABAP development tools for Eclipse (ADT). -* - Choose F9 to run the class. -* - Check the console output. -* - To understand the context and the ABAP syntax used, refer to the -* notes included in the class as comments or refer to the respective -* topic in the ABAP Keyword Documentation. -* - Due to the amount of console output, the examples contain numbers -* (e.g. 1) ..., 2) ..., 3) ...) for the individual example sections. -* Also, the variable name is displayed in most cases. So to find -* the relevant output in the console easier and faster, just search -* for the number/variable name in the console (CTRL+F in the console) -* or use the debugger. -* -* ----------------------------- NOTE ----------------------------------- -* The code presented in this class is intended only to support the ABAP -* cheat sheets. It is not intended for direct use in a production system -* environment. The code examples in the ABAP cheat sheets are primarily -* intended to provide a better explanation and visualization of the -* syntax and semantics of ABAP statements, not to solve concrete -* programming tasks. For production application programs, you should -* always work out your own solution for each individual case. There is -* no guarantee for the correctness or completeness of the code. -* Furthermore, there is no legal responsibility or liability for any -* errors or their consequences that may occur when using the the example -* code. -* -*********************************************************************** -"!

ABAP cheat sheet: Working with XML and JSON in ABAP

-"! Example that demonstrates working with XML and JSON in ABAP..
Choose F9 in ADT to run the class. -CLASS zcl_demo_abap_xml_json DEFINITION - PUBLIC - FINAL - CREATE PUBLIC . - - PUBLIC SECTION. - INTERFACES: if_oo_adt_classrun, - "This interface is implemented for serializing and - "deserialzing instances of classes (objects). - if_serializable_object. - CLASS-METHODS class_constructor. - - PROTECTED SECTION. - PRIVATE SECTION. - CLASS-METHODS format IMPORTING input TYPE data - xml TYPE abap_bool DEFAULT abap_true - RETURNING VALUE(string) TYPE string. - TYPES c50 TYPE c LENGTH 50. - TYPES c50_tab_type TYPE TABLE OF c50 WITH EMPTY KEY. - TYPES x30 TYPE x LENGTH 30. - TYPES x30_tab_type TYPE TABLE OF x30 WITH EMPTY KEY. - - "The following instance attribues and methods are used for serializing and - "deserialzing instances of classes (objects) - DATA: attr_string_a TYPE string, - attr_string_b TYPE string, - attr_concat_string TYPE string, - attr_lowercase_str TYPE string. - METHODS: concatenate_string, - lowercase_string, - "The following method can only have output parameters. - "For each output parameter of the serialize_helper method, you must specify - "an identically named input parameter of the deserialize_helper method - "with the same type. - serialize_helper EXPORTING attr_string_a TYPE string - attr_string_b TYPE string - attr_concat_string TYPE string, - "This method can only have input parameters. - deserialize_helper IMPORTING attr_string_a TYPE string - attr_string_b TYPE string - attr_concat_string TYPE string. -ENDCLASS. - - - -CLASS zcl_demo_abap_xml_json IMPLEMENTATION. - - METHOD if_oo_adt_classrun~main. - - out->write( |ABAP Cheat Sheet Example: Working with XML and JSON in ABAP\n\n| ). - out->write( |1) Excursion: Converting string <-> xstring| ). - "In the following examples, many operations are performed using binary data. - "This excursion shows the conversion of string to xstring and the other way round - "using a codepage. The examples use UTF-8. - "For this purpose, you can, for example, use the cl_abap_conv_codepage class - "and the XCO library. - - "Storing XML data in a data object of type string - DATA(xml_string) = - `` && - ` ` && - ` LH` && - ` 400` && - ` ` && - ` Frankfurt` && - ` FRA` && - ` ` && - ` ` && - ` ` && - ` Berlin` && - ` SXF` && - ` ` && - ` ` && - ` ` && - ` ` && - ` DL` && - ` 1984` && - ` ` && - ` San Francisco` && - ` SFO` && - ` ` && - ` ` && - ` ` && - ` New York` && - ` JFK` && - ` ` && - ` ` && - ` ` && - ``. - - "string -> xstring - "Note: UTF-8 is used by default. Here, it is specified explicitly. - "Conversion errors are caught using the cx_sy_conversion_codepage class. - TRY. - DATA(conv_xstring) = cl_abap_conv_codepage=>create_out( codepage = `UTF-8` )->convert( xml_string ). - CATCH cx_sy_conversion_codepage. - ENDTRY. - - "xstring -> string - DATA(conv_string) = cl_abap_conv_codepage=>create_in( )->convert( conv_xstring ). - - "As an alternative, you can use methods of the XCO library. - "string -> xstring - DATA(conv_xstring_xco) = xco_cp=>string( xml_string - )->as_xstring( xco_cp_character=>code_page->utf_8 - )->value. - - "xstring -> string - DATA(conv_string_xco) = xco_cp=>xstring( conv_xstring_xco - )->as_string( xco_cp_character=>code_page->utf_8 - )->value. - - conv_string = format( conv_string ). - conv_string_xco = format( conv_string_xco ). - out->write( |\n| ). - out->write( `Results of the xstring to string conversions:` ). - out->write( |\n| ). - out->write( conv_string ). - out->write( |\n| ). - out->write( conv_string_xco ). - -********************************************************************** - - out->write( zcl_demo_abap_aux=>heading( `2) Processing XML Using Class Libraries` ) ). - out->write( |Excursion: Usable iXML/sXML Classes and Interfaces\n\n| ). - "Using a released CDS view, classes and interfaces are retrieved that - "have 'ixml' and 'sxml' in the name for you to explore the released classes - "and interfaces in this context. - - SELECT ReleasedObjectType, ReleasedObjectName, ReleaseState - FROM i_apisforclouddevelopment - WHERE releasestate = 'RELEASED' - AND - ( ReleasedObjectType = 'CLAS' OR ReleasedObjectType = 'INTF' ) - AND - ( ReleasedObjectName LIKE '%IXML%' OR ReleasedObjectName LIKE '%SXML%' ) - INTO TABLE @DATA(released_xml_libs). - - out->write( `No output. You can check the internal table content in the debugger to view the usable artifacts.` ). - -*********************************************************************** - - out->write( zcl_demo_abap_aux=>heading( `3) Creating XML Data Using iXML` ) ). - "In the following example, XML data is created using the iXML library. - "This is done by creating DOM nodes step by step. The nodes are created as - "elements and attributes. Content is inserted into the XML data. - "The example uses an appropriate attribute setting so that the result - "represents XML data in asXML format. - "Note: You can check out more examples in the system by choosing CTRL + - "SHIFT + A in ADT and search for *demo_ixml*. - "For more information on the classes/methods used, check the documentation - "by choosing F2 in ADT when placing the cursor on a class/methods. - - "Creating one factory object of the access class cl_ixml_core using the - "create method. The object is used to access the iXML library. - DATA(ixml_cr) = cl_ixml_core=>create( ). - - "Creating a document - DATA(document_cr) = ixml_cr->create_document( ). - - "Step-by-step creation of DOM nodes - "Creating a root node - DATA(root) = document_cr->create_element_ns( name = 'abap' - prefix = 'asx' ). - root->set_attribute_ns( name = 'asx' - prefix = 'xmlns' - value = 'http://www.sap.com/abapxml' ). - root->set_attribute_ns( name = 'version' - value = '1.0' ). - document_cr->append_child( root ). - DATA(xml_node1) = document_cr->create_element_ns( prefix = 'asx' - name = 'values' ). - root->append_child( xml_node1 ). - DATA(xml_node2) = document_cr->create_element_ns( name = 'STRING' ). - xml_node1->append_child( xml_node2 ). - xml_node2->append_child( document_cr->create_text( 'Hello ABAP' ) ). - - "Creating a renderer (for rendering the XML document into the output stream) - DATA xml_doc TYPE xstring. - ixml_cr->create_renderer( document = document_cr - ostream = ixml_cr->create_stream_factory( )->create_ostream_xstring( string = xml_doc ) - )->render( ). - - "Getting XML data - DATA(xml_output) = format( cl_abap_conv_codepage=>create_in( )->convert( xml_doc ) ). - out->write( xml_output ). - -*********************************************************************** - - out->write( zcl_demo_abap_aux=>heading( `4) Parsing XML Data Using iXML` ) ). - "The example covers the following aspects: - "- Parsing XML data to a DOM object in one go - "- Directly reading nodes using various iXML methods - "- Directly reading nodes using element names - "- Reading using iterators, i.e. going over the XML nodes one after another - "- During the iteration, ... - " ... node properties are extracted using various iXML methods - " (and stored in an internal table for display purposes). - " ... the XML data is modified. - " ... a new element is created. - "- Rendering XML data - - "Internal table to store node properties for display purposes - DATA properties TYPE string_table. - - "Creating simple demo XML data to be used in the example - TRY. - DATA(some_xml) = cl_abap_conv_codepage=>create_out( )->convert( - `` && - ` hallo` && - ` how` && - ` are` && - `` ). - CATCH cx_sy_conversion_codepage. - ENDTRY. - - "Creating one factory object of the access class cl_ixml_core using the - "create method. It is used to access the iXML library. - DATA(ixml_pa) = cl_ixml_core=>create( ). - "Creaing an input stream that is used for the input of XML data - DATA(stream_factory_pa) = ixml_pa->create_stream_factory( ). - "Creating an XML document stored in DOM format in the memory - DATA(document_pa) = ixml_pa->create_document( ). - "Creating a parser - "It requires the following input parameters: input stream to be parsed, - "the XML document to which the stream is parsed, a factory required to create a stream - DATA(parser_pa) = ixml_pa->create_parser( - istream = stream_factory_pa->create_istream_xstring( string = some_xml ) - document = document_pa - stream_factory = stream_factory_pa ). - - "Parsing XML data to a DOM representation in one go. It is put in the memory. - "Note: You can also parse sequentially, and not in one go. - DATA(parsing_check) = parser_pa->parse( ). - IF parsing_check = 0. "Parsing was successful - - "Directly reading nodes using various iXML methods - - "Accessing the root element of the DOM. It can be used as the initial node - "for accessing subnodes. - "You can check the content of the variables in the debugger. - "Note: Multiple methods are available to further process the nodes. - DATA(root_element) = document_pa->get_root_element( ). - "First subnode - DATA(child_element) = root_element->get_first_child( ). - "Getting the value of that node - DATA(child_element_value) = child_element->get_value( ). - "Next adjacent node/getting the value - DATA(next_element_value) = child_element->get_next( )->get_value( ). - - "Directly reading nodes using element names - "The result is the first element searched for. - DATA(element_by_name) = document_pa->find_from_name( name = `word3` )->get_value( ). - "A lot more options are available such as access by attributes. - - "Reading using iterators, i.e. going over the XML nodes sequentially - - "Creating an iterator - DATA(iterator_pa) = document_pa->create_iterator( ). - DO. - "For the iteration, you can use the get_next method to process the nodes one after another. - "Note: Here, all nodes are respected. You can also create filters to go over specific nodes. - DATA(node_i) = iterator_pa->get_next( ). - IF node_i IS INITIAL. - EXIT. - ELSE. - "Extracting properties - "For display purposes, the properties are stored in an internal table. - APPEND |gid: { node_i->get_gid( ) } / type: { node_i->get_type( ) } / name: { node_i->get_name( ) } / value: { node_i->get_value( ) }| TO properties. - ENDIF. - - IF node_i->get_type( ) = if_ixml_node=>co_node_text. - "Modifying values - "Here, the values are capitalized. - node_i->set_value( to_upper( node_i->get_value( ) ) ). - ENDIF. - - "Creating a new element - IF node_i->get_value( ) = 'are'. - document_pa->create_simple_element_ns( name = 'word4' - value = 'you' - parent = node_i->get_parent( ) ). - ENDIF. - ENDDO. - - "Creating a renderer - DATA xml_pa TYPE xstring. - ixml_pa->create_renderer( document = document_pa - ostream = ixml_pa->create_stream_factory( )->create_ostream_xstring( string = xml_pa ) - )->render( ). - - "Getting XML - DATA(output_ixml_parsing) = format( cl_abap_conv_codepage=>create_in( )->convert( xml_pa ) ). - - out->write( output_ixml_parsing ). - out->write( |\n| ). - out->write( `Node properties:` ). - out->write( properties ). - ELSE. - out->write( `Parsing was not successful.` ). - ENDIF. - -*********************************************************************** - - out->write( zcl_demo_abap_aux=>heading( `5) Creating XML Data Using sXML (Token-Based Rendering)` ) ). - "For sXML, there are specialized writer classes, such as CL_SXML_STRING_WRITE. - "Writers created with this class render XML data to a byte string. - "The XML 1.0 format and UTF-8 are used by default in the create method. - "Here, the parameters are specified explicitly. - "Note: The interface IF_SXML_WRITER contains the components that are valid - "for all readers (the abstract superclass CL_SXML_WRITER includes this - "interface as well as implementations for all readers). In the example below, - "a cast is required so as to access special methods (such as open_element). - - DATA(writer) = CAST if_sxml_writer( cl_sxml_string_writer=>create( type = if_sxml=>co_xt_xml10 - encoding = 'UTF-8' ) ). - - TRY. - "Creating nodes (the order of the nodes is important) - writer->open_element( name = 'flights' ). - writer->open_element( name = 'flight' ). - writer->open_element( name = 'carrier' ). - writer->write_value( 'LH' ). - writer->close_element( ). - writer->open_element( name = 'flightnumber' ). - writer->write_value( '400' ). - writer->close_element( ). - writer->close_element( ). - writer->open_element( name = 'flight' ). - writer->open_element( name = 'carrier' ). - writer->write_value( 'DL' ). - writer->close_element( ). - writer->open_element( name = 'flightnumber' ). - writer->write_value( '1984' ). - writer->close_element( ). - writer->close_element( ). - writer->close_element( ). - CATCH cx_sxml_state_error INTO DATA(error_token). - out->write( error_token->get_text( ) ). - ENDTRY. - - "Getting XML data - "The XML data can be retrieved with the GET_OUTPUT method. - "Also here, a cast is required. The result is of type xstring. - DATA(xml_sxml) = CAST cl_sxml_string_writer( writer )->get_output( ). - - DATA(output_sxml_token_rendering) = format( cl_abap_conv_codepage=>create_in( )->convert( xml_sxml ) ). - out->write( output_sxml_token_rendering ). - -*********************************************************************** - - out->write( zcl_demo_abap_aux=>heading( `6) Creating XML Data using sXML (Object-Oriented Rendering)` ) ). - - DATA(writer_oo) = CAST if_sxml_writer( cl_sxml_string_writer=>create( type = if_sxml=>co_xt_xml10 - encoding = 'UTF-8' ) ). - - TRY. - writer_oo->write_node( writer_oo->new_open_element( name = 'flights' ) ). - - writer_oo->write_node( writer_oo->new_open_element( name = 'flight' ) ). - writer_oo->write_node( writer_oo->new_open_element( name = 'carrier' ) ). - DATA(val) = writer_oo->new_value( ). - val->set_value( 'AZ' ). - writer_oo->write_node( val ). - writer_oo->write_node( writer_oo->new_close_element( ) ). - writer_oo->write_node( writer_oo->new_open_element( name = 'flightnumber' ) ). - val = writer_oo->new_value( ). - val->set_value( '788' ). - writer_oo->write_node( val ). - writer_oo->write_node( writer_oo->new_close_element( ) ). - writer_oo->write_node( writer_oo->new_close_element( ) ). - - writer_oo->write_node( writer_oo->new_open_element( name = 'flight' ) ). - writer_oo->write_node( writer_oo->new_open_element( name = 'carrier' ) ). - val = writer_oo->new_value( ). - val->set_value( 'JL' ). - writer_oo->write_node( val ). - writer_oo->write_node( writer_oo->new_close_element( ) ). - writer_oo->write_node( writer_oo->new_open_element( name = 'flightnumber' ) ). - val = writer_oo->new_value( ). - val->set_value( '407' ). - writer_oo->write_node( val ). - writer_oo->write_node( writer_oo->new_close_element( ) ). - writer_oo->write_node( writer_oo->new_close_element( ) ). - - writer_oo->write_node( writer_oo->new_close_element( ) ). - CATCH cx_sxml_state_error INTO DATA(error_oo). - out->write( error_oo->get_text( ) ). - ENDTRY. - - DATA(xml_sxml_oo_rendering) = CAST cl_sxml_string_writer( writer_oo )->get_output( ). - - DATA(output_sxml_oo_rendering) = format( cl_abap_conv_codepage=>create_in( )->convert( xml_sxml_oo_rendering ) ). - out->write( output_sxml_oo_rendering ). - -*********************************************************************** - - out->write( zcl_demo_abap_aux=>heading( `7) Parsing XML Data using sXML (Token-Based Parsing)` ) ). - - "Creating demo XML data to be used in the example - TRY. - DATA(xml_to_parse) = cl_abap_conv_codepage=>create_out( )->convert( - `` && - `` && - ` ` && - ` A` && - ` 01-01-2024` && - ` ` && - ` ` && - ` abc` && - ` def` && - ` ghi` && - ` jkl` && - ` ` && - `` ). - CATCH cx_sy_conversion_codepage. - ENDTRY. - - "Creating an internal table for display purposes - DATA: BEGIN OF node_info, - node_type TYPE string, - prefix TYPE string, - name TYPE string, - nsuri TYPE string, - value_type TYPE string, - value TYPE string, - value_raw TYPE xstring, - END OF node_info, - nodes_tab LIKE TABLE OF node_info. - - "Creating reader - "Note: See the comments for the writer above which is similar. For readers, - "the interface IF_SXML_READER exists. In this example, no special methods - "are used. Therefore, a cast is not carried out. - DATA(reader) = cl_sxml_string_reader=>create( xml_to_parse ). - "DATA(reader_cast) = CAST if_sxml_reader( cl_sxml_string_reader=>create( xml_oo ) ). - - "To iterate accros all nodes, you can call the NEXT_NODE method. - TRY. - DO. - "Check out other available methods in ADT by placing the cursor behind -> - "and choosing CTRL + Space. - reader->next_node( ). - - "When reaching the end of the XML data, the loop is exited. - IF reader->node_type = if_sxml_node=>co_nt_final. - EXIT. - ENDIF. - - "You can access the properties of the node directly. - "For display purposes, the property information is stored in an internal table. - "The demo XML data that is used here does not include all properties. Therefore, - "the values for these are initial. - - "Node type, see the interface if_sxml_node - DATA(node_type) = SWITCH #( reader->node_type WHEN if_sxml_node=>co_nt_initial THEN `CO_NT_INITIAL` - WHEN if_sxml_node=>co_nt_element_open THEN `CO_NT_ELEMENT_OPEN` - WHEN if_sxml_node=>co_nt_element_close THEN `CO_NT_ELEMENT_CLOSE` - WHEN if_sxml_node=>co_nt_value THEN `CO_NT_VALUE` - WHEN if_sxml_node=>co_nt_attribute THEN `CO_NT_ATTRIBUTE` - ELSE `Error` ). - - DATA(prefix) = reader->prefix. "Namespace prefix - DATA(name) = reader->name. "Name of the element - DATA(nsuri) = reader->nsuri. "Namespace URI - - "Value type, see the interface if_sxml_value - DATA(value_type) = SWITCH #( reader->value_type WHEN 0 THEN `Initial` - WHEN if_sxml_value=>co_vt_none THEN `CO_VT_NONE` - WHEN if_sxml_value=>co_vt_text THEN `CO_VT_TEXT` - WHEN if_sxml_value=>co_vt_raw THEN `CO_VT_RAW` - WHEN if_sxml_value=>co_vt_any THEN `CO_VT_ANY` - ELSE `Error` ). - - DATA(value) = reader->value. "Character-like value (if it is textual data) - DATA(value_raw) = reader->value_raw. "Byte-like value (if it is raw data) - - APPEND VALUE #( node_type = node_type - prefix = prefix - name = name - nsuri = nsuri - value_type = value_type - value = value - value_raw = value_raw ) TO nodes_tab. - - "Once the method is called, you can directly access the attributes of the reader with the required - "properties of the node. When the parser is on the node of an element opening, you can use the method - "NEXT_ATTRIBUTE to iterate across the XML element attributes. - 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 = `attribute` - prefix = reader->prefix - name = reader->name - nsuri = reader->nsuri - value = reader->value - value_raw = reader->value_raw ) TO nodes_tab. - ENDDO. - ENDIF. - ENDDO. - CATCH cx_sxml_state_error INTO DATA(error_parse_token). - out->write( error_parse_token->get_text( ) ). - ENDTRY. - - out->write( `Node properties:` ). - out->write( nodes_tab ). - -*********************************************************************** - - out->write( zcl_demo_abap_aux=>heading( `8) Parsing XML Data using sXML (Object-Oriented Parsing)` ) ). - - CLEAR nodes_tab. - DATA(reader_oo) = cl_sxml_string_reader=>create( xml_to_parse ). - - TRY. - DO. - "To iterate accros all nodes, you can call the READ_NEXT_NODE method. - "When the end of the XML data is reached, the returned value is initial. - DATA(node_oo) = reader_oo->read_next_node( ). - IF node_oo IS INITIAL. - EXIT. - ENDIF. - - "In object-oriented parsing, methods for token-based parsing are wrapped. - "An object-oriented access to the node is provided. - "References to objects that represent the current node are returned. - - "Getting the node type - DATA(n_type) = node_oo->type. - - "If the parser is currently on the node of an element opening, - "the node object has the class CL_SXML_OPEN_ELEMENT that implements the - "interface IF_SXML_OPEN_ELEMENT. With the methods included, you can - "access the XML attributes of the element, e.g. using the GET_ATTRIBUTES - "method to put the references for all attributes into an internal table. - "To access the attributes, a downcast is required. - - CASE n_type. - WHEN if_sxml_node=>co_nt_element_open. - DATA(open_element) = CAST if_sxml_open_element( node_oo ). - - APPEND VALUE #( node_type = `open element` - prefix = open_element->prefix - name = open_element->qname-name - nsuri = open_element->qname-namespace - ) TO nodes_tab. - - DATA(attributes) = open_element->get_attributes( ). - - LOOP AT attributes INTO DATA(attribute). - APPEND VALUE #( node_type = `attribute` - prefix = open_element->prefix - name = open_element->qname-name - nsuri = open_element->qname-namespace - value = SWITCH #( attribute->value_type WHEN if_sxml_value=>co_vt_text THEN attribute->get_value( ) ) - value_raw = SWITCH #( attribute->value_type WHEN if_sxml_value=>co_vt_raw THEN attribute->get_value_raw( ) ) - ) TO nodes_tab. - ENDLOOP. - - WHEN if_sxml_node=>co_nt_element_close. - DATA(close_element) = CAST if_sxml_close_element( node_oo ). - - APPEND VALUE #( node_type = `close element` - prefix = open_element->prefix - name = open_element->qname-name - nsuri = open_element->qname-namespace - ) TO nodes_tab. - - WHEN if_sxml_node=>co_nt_value. - DATA(value_node_oo) = CAST if_sxml_value_node( node_oo ). - - APPEND VALUE #( node_type = `value` - value = SWITCH #( value_node_oo->value_type WHEN if_sxml_value=>co_vt_text THEN value_node_oo->get_value( ) ) - value_raw = SWITCH #( value_node_oo->value_type WHEN if_sxml_value=>co_vt_raw THEN value_node_oo->get_value_raw( ) ) - ) TO nodes_tab. - - WHEN OTHERS. - APPEND VALUE #( node_type = `Error` ) TO nodes_tab. - ENDCASE. - ENDDO. - CATCH cx_sxml_state_error INTO DATA(error_parse_oo). - out->write( error_parse_oo->get_text( ) ). - ENDTRY. - - out->write( `Node properties:` ). - out->write( nodes_tab ). - -*********************************************************************** - - out->write( zcl_demo_abap_aux=>heading( `XML Transformations` ) ). - - out->write( |9) Excursion: Available ABAP Cheat Sheet Transformations in the System\n\n| ). - "Excursion using the XCO library. In this example, tranformation programs are retrieved. - "A filter is applied. Because of a filter that is applied, only the ABAP cheat sheet - "transformation programs are returned. - - DATA(filter) = xco_cp_abap_repository=>object_name->get_filter( - xco_cp_abap_sql=>constraint->contains_pattern( 'ZDEMO_ABAP_%' ) ). - - DATA(filtered_transformations) = xco_cp_abap_repository=>objects->xslt->where( VALUE #( ( filter ) - ) )->in( xco_cp_abap=>repository )->get( ). - - IF filtered_transformations IS NOT INITIAL. - TYPES cst TYPE TABLE OF sxco_tf_object_name WITH EMPTY KEY. - DATA(cheat_sheet_transformations) = VALUE cst( FOR tr IN filtered_transformations ( tr->name ) ). - out->write( cheat_sheet_transformations ). - out->write( |\n| ). - out->write( `The code contains an implementation that gets all the transformations in the system.` ). - out->write( `You can check the content of the variable in the debugger. Among the transformations is the predefined identity transformation ID.` ). - ENDIF. - - "Getting all transformations in the system - "You can check the table content in the debugger. - DATA(all_transformations) = xco_cp_abap_repository=>objects->xslt->all->in( xco_cp_abap=>repository )->get( ). - IF all_transformations IS NOT INITIAL. - DATA(all_transformations_in_system) = VALUE cst( FOR tr IN all_transformations ( tr->name ) ). - ENDIF. - -*********************************************************************** - - out->write( zcl_demo_abap_aux=>heading( `10) Transforming XML to XML Using XSLT` ) ). - "In this example, XML is transformed to XML. For this purpose, a simple XSLT - "program does the following: - "- All nodes and attributes are copied from the source XML to the target XML - " without any changes. - "- A match on two elements is performed. If matched, two new elements are created - " in the target XML. In this operation, calculations are carried out (free seats - " and the occupancy rate based on the values of maximum and occupied seats). - "Note: - "- The element names in the demo XML data are capitalized on purpose because the - " XML data is used in another example that uses the asXML format. In deserializations - " of XML data to ABAP data, the elements that are deserialized must be capitalized - " so that they can be identified. - "Tranformations are performed using CALL TRANSFORMATION statements. - - "Creating demo XML data to be used in the example - TRY. - DATA(xml_flights) = cl_abap_conv_codepage=>create_out( codepage = `UTF-8` )->convert( - `` && - ` ` && - ` AA` && - ` 17` && - ` 385` && - ` 369` && - ` ` && - ` ` && - ` LH` && - ` 400` && - ` 330` && - ` 319` && - ` ` && - `` ). - CATCH cx_sy_conversion_codepage. - ENDTRY. - - DATA xml_a TYPE xstring. - - CALL TRANSFORMATION zdemo_abap_xslt_fl - SOURCE XML xml_flights - RESULT XML xml_a. - - DATA(conv_xml_a) = format( cl_abap_conv_codepage=>create_in( )->convert( xml_a ) ). - out->write( conv_xml_a ). - -*********************************************************************** - - out->write( zcl_demo_abap_aux=>heading( `11) Transforming ABAP to XML Using XSLT` ) ). - "In the example, data entries are retrieved from a database table. Appropriate names for the - "table columns are used with the AS addition so that the transformation can be carried - "out based on the selected data. - "Note: The resulting XML has the asXML format. - - SELECT carrid AS carrier, - connid AS connectionid, - seatsmax AS maxSeats, - seatsocc AS occSeats - FROM zdemo_abap_fli - WHERE carrid = 'AZ' - INTO TABLE @DATA(fli_itab) - UP TO 2 ROWS. - - DATA xml_b TYPE xstring. - - CALL TRANSFORMATION zdemo_abap_xslt_fl - SOURCE flights = fli_itab - RESULT XML xml_b. - - DATA(conv_xml_b) = format( cl_abap_conv_codepage=>create_in( )->convert( xml_b ) ). - out->write( conv_xml_b ). - -*********************************************************************** - - out->write( zcl_demo_abap_aux=>heading( `12) ABAP <-> XML using Simple Transformations (1)` ) ). - "The following simple transformation examples transform ABAP to XML and back. The - "Simple Transformation is implemented in a way to transform to the HTML format. - "This example transforms string tables to html. - - DATA(string_table_a) = VALUE string_table( ( `abc` ) ( `def` ) ( `ghi` ) ). - - DATA xml_c TYPE xstring. - - "ABAP -> XML - CALL TRANSFORMATION zdemo_abap_st_strhtml - SOURCE string_table = string_table_a - RESULT XML xml_c. - - DATA(conv_xml_c) = format( cl_abap_conv_codepage=>create_in( )->convert( xml_c ) ). - out->write( `ABAP -> XML` ). - out->write( conv_xml_c ). - out->write( |\n| ). - - "XML -> ABAP - DATA string_table_b TYPE string_table. - CALL TRANSFORMATION zdemo_abap_st_strhtml - SOURCE XML xml_c - RESULT string_table = string_table_b. - - out->write( `XML -> ABAP` ). - out->write( string_table_b ). - -*********************************************************************** - - out->write( zcl_demo_abap_aux=>heading( `13) ABAP <-> XML using Simple Transformations (2)` ) ). - "In this example, an internal table is transformed to XML using Simple Transformation. - "HTML tags are inserted into the XML data as literals. - - SELECT carrid, carrname, currcode, url - FROM zdemo_abap_carr - INTO TABLE @DATA(carr_tab_a) - UP TO 2 ROWS. - - "ABAP -> XML - DATA str_a TYPE string. - - "The following CALL TRANSFORMATION statement includes the OPTIONS - "addition. In this example, the XML header should not be added. - "So, you can take the resulting html and test it in an HTML viewer. - - CALL TRANSFORMATION zdemo_abap_st_carrhtml - SOURCE carrier_info = carr_tab_a - RESULT XML str_a - OPTIONS xml_header = 'NO'. - - out->write( `ABAP -> XML` ). - out->write( format( str_a ) ). - out->write( |\n| ). - - "XML -> ABAP - DATA carr_tab_b LIKE carr_tab_a. - - CALL TRANSFORMATION zdemo_abap_st_carrhtml - SOURCE XML str_a - RESULT carrier_info = carr_tab_b. - - out->write( `XML -> ABAP` ). - out->write( carr_tab_b ). - -*********************************************************************** - - out->write( zcl_demo_abap_aux=>heading( `ABAP <-> XML using XSLT (Using the Predefined Identity Transformation ID)` ) ). - "The following examples demonstrate serializations (ABAP to XML) and deserializations (XML to ABAP) - "using the predefined identity transformation ID. - "Note: In doing so, ABAP data is transformed to their asXML representations that can be used as an - " intermediate format and which define a mapping between ABAP data and XML. - - out->write( |14) Elementary type\n\n| ). - "The example uses type string as an elementary type. - - "ABAP -> XML - DATA xml_d TYPE xstring. - DATA(str_b) = `This is some string.`. - - CALL TRANSFORMATION id SOURCE txt = str_b - RESULT XML xml_d. - - DATA(conv_xml_d) = cl_abap_conv_codepage=>create_in( )->convert( xml_d ). - out->write( `ABAP -> XML` ). - out->write( format( conv_xml_d ) ). - out->write( |\n| ). - - "XML -> ABAP - DATA str_c TYPE string. - CALL TRANSFORMATION id SOURCE XML xml_d - RESULT txt = str_c. - - out->write( `XML -> ABAP` ). - out->write( str_c ). - -************************************************************************ - - out->write( zcl_demo_abap_aux=>heading( `15) Structures` ) ). - - SELECT SINGLE carrid, carrname, currcode, url - FROM zdemo_abap_carr - WHERE carrid = 'LH' - INTO @DATA(carr_struc_a). - - "ABAP -> XML - DATA xml_e TYPE xstring. - CALL TRANSFORMATION id SOURCE structure = carr_struc_a - RESULT XML xml_e. - - DATA(conv_xml_e) = cl_abap_conv_codepage=>create_in( )->convert( xml_e ). - out->write( `ABAP -> XML` ). - out->write( format( conv_xml_e ) ). - out->write( |\n| ). - - "XML -> ABAP - DATA carr_struc_b LIKE carr_struc_a. - CALL TRANSFORMATION id SOURCE XML xml_e - RESULT structure = carr_struc_b. - - out->write( `XML -> ABAP` ). - out->write( carr_struc_b ). - out->write( |\n| ). - -************************************************************************ - - out->write( zcl_demo_abap_aux=>heading( `16) Internal tables` ) ). - - SELECT carrid, connid, fldate, price, currency - FROM zdemo_abap_fli - WHERE carrid = 'JL' - INTO TABLE @DATA(fli_tab_a) - UP TO 2 ROWS. - - "ABAP -> XML - DATA xml_f TYPE xstring. - CALL TRANSFORMATION id SOURCE itab = fli_tab_a - RESULT XML xml_f. - - DATA(conv_xml_f) = cl_abap_conv_codepage=>create_in( )->convert( xml_f ). - out->write( `ABAP -> XML` ). - out->write( format( conv_xml_f ) ). - out->write( |\n| ). - - "XML -> ABAP - DATA fli_tab_b LIKE fli_tab_a. - CALL TRANSFORMATION id SOURCE XML xml_f - RESULT itab = fli_tab_b. - - out->write( `XML -> ABAP` ). - out->write( fli_tab_b ). - -************************************************************************ - - out->write( zcl_demo_abap_aux=>heading( `17) Data References` ) ). - - DATA(dref_a) = NEW i( 123 ). - - "ABAP -> XML - DATA xml_g TYPE xstring. - CALL TRANSFORMATION id SOURCE dref = dref_a - RESULT XML xml_g. - - DATA(conv_xml_g) = cl_abap_conv_codepage=>create_in( )->convert( xml_g ). - - out->write( `ABAP -> XML` ). - out->write( format( conv_xml_g ) ). - out->write( |\n| ). - - "XML -> ABAP - DATA dref_b LIKE dref_a. - CALL TRANSFORMATION id SOURCE XML xml_g - RESULT dref = dref_b. - - out->write( `XML -> ABAP` ). - out->write( dref_b->* ). - -************************************************************************ - - out->write( zcl_demo_abap_aux=>heading( `18) Object References` ) ). - "The following example demonstrates the serialization and deserialization of - "instances of classes (objects). For example, to serialize instance attributes, - "classes must implement the if_serializable_object interface. By default, all instance - "attributes of an object are serialized, regardless of their visibility section. - "However, you can change this behavior using the serialize_helper and deserialize_helper - "instance methods. As a result of the transformation, you get an asXML representation of - "the object. - "The example is implemented as follows: - "- The class implements the if_serializable_object interface. - "- There are 4 instance attributes of type string. - "- There are two instance methods: - " - One method concatenates two of the strings and assigns the resulting string to - " another string. - " - Another method concatenates two strings and converts the string to lowercase. - " The result is assigned to another string. - "- Serialization preserves instance attribute values in the asXML representation of the - " object. - "- During deserialization, the instance attribute values are transformed back and can - " be accessed. - "- The example includes the implementation of the serialize_helper and deserialize_helper - " instance methods. Without implementation, all instance attributes would be - " serialized/deserialized. The sample implementation limits serialization/deserialization. - " The fourth instance attribute, which is converted to a lowercase string when calling the - " method, is not part of the serialization/deserialization. See the implementation of the - " serialize_helper and deserialize_helper instance methods. They explicitly specify what - " to serialize and deserialize. - "- Note: For each output parameter of the serialize_helper method, you must specify an - " identically-named input parameter of the deserialize_helper method. The parameters must - " have the same type. - - DATA(oref_a) = NEW zcl_demo_abap_xml_json( ). - oref_a->attr_string_a = `AB`. - oref_a->attr_string_b = `AP`. - oref_a->concatenate_string( ). - oref_a->lowercase_string( ). - - out->write( `Value of instance attribute attr_lowercase_str for the created instance (before serialization/deserialization):` ). - out->write( oref_a->attr_lowercase_str ). - out->write( |\n| ). - - "ABAP -> XML - DATA xml_oref_a TYPE xstring. - CALL TRANSFORMATION id SOURCE oref = oref_a - RESULT XML xml_oref_a. - - DATA(conv_xml_oref_a) = cl_abap_conv_codepage=>create_in( )->convert( xml_oref_a ). - - out->write( `ABAP -> XML` ). - out->write( format( conv_xml_oref_a ) ). - out->write( |\n| ). - - "XML -> ABAP - DATA oref_b LIKE oref_a. - CALL TRANSFORMATION id SOURCE XML xml_oref_a - RESULT oref = oref_b. - - out->write( `XML -> ABAP` ). - out->write( oref_b->attr_string_a ). - out->write( oref_b->attr_string_b ). - out->write( oref_b->attr_concat_string ). - out->write( |\n| ). - IF oref_b->attr_lowercase_str IS INITIAL. - out->write( `The instance attribute attr_lowercase_str is initial. The serialization/deserialization is restricted.` ). - ENDIF. - -************************************************************************ - - out->write( zcl_demo_abap_aux=>heading( `19) CALL TRANSFORMATION Syntax: Specifying Transformations` ) ). - "As already covered in the examples above, transformations are specified after - "CALL TRANSFORMATION. They are either ... - - "... XSLT programs - CALL TRANSFORMATION zdemo_abap_st_carrhtml SOURCE carrier_info = carr_tab_a - RESULT XML str_a. - - "... predefined identity transformations - CALL TRANSFORMATION id SOURCE dref = dref_a - RESULT XML xml_g. - - "... dynamically specified transformation (valid for both XSLT and ST). In the examples above, - "the transformation is specified statically. Dynamic specifications are possible. A - "character-like data object in uppercase letters is expected in parentheses (either a named - "or unnamed data objects). - CALL TRANSFORMATION ('ID') SOURCE dref = dref_a - RESULT XML xml_g. - - "If a dynamically specified transformation is not found, an exception of the class - "CX_INVALID_TRANSFORMATION is raied. The example uses a named data object. - DATA(notr) = 'NON_EXISTENT_TRANSFORMATION'. - TRY. - CALL TRANSFORMATION (notr) SOURCE dref = dref_a - RESULT XML xml_g. - CATCH cx_invalid_transformation INTO DATA(error_non). - out->write( error_non->get_text( ) ). - ENDTRY. - - "... Simple Transformation - CALL TRANSFORMATION zdemo_abap_st_carrhtml SOURCE XML str_a - RESULT carrier_info = carr_tab_b. - -************************************************************************ - - out->write( zcl_demo_abap_aux=>heading( `20) CALL TRANSFORMATION Syntax: Sources of Transformations` ) ). - "The following examples use the predefined identity transformation ID. - "The result is asXML data and stored in a variable of type xstring. - "Multiple options and variants are possible. The examples cover a selection. - - out->write( `********** Source options for transforming XML data **********` ). - out->write( |\n| ). - - "Source: XML data in a data object of type string. It is implicitly transformed to - "XML in this case. - "Note: It must have character-like XML data in XML 1.0 format. - DATA(str_d) = `Hello world`. - DATA xml_h TYPE xstring. - CALL TRANSFORMATION id SOURCE XML str_d - RESULT XML xml_h. - - DATA(conv_xml_h) = cl_abap_conv_codepage=>create_in( )->convert( xml_h ). - - out->write( `Source: XML data in data object of type string` ). - out->write( format( conv_xml_h ) ). - out->write( |\n| ). - - "Source: XML data in a data object of type xstring - DATA(xml_i) = cl_abap_conv_codepage=>create_out( )->convert( `Hi ABAP` ). - DATA xml_j TYPE xstring. - CALL TRANSFORMATION id SOURCE XML xml_i - RESULT XML xml_j. - - DATA(conv_xml_j) = cl_abap_conv_codepage=>create_in( )->convert( xml_j ). - out->write( `Source: XML data in a data object of type xstring` ). - out->write( format( conv_xml_j ) ). - out->write( |\n| ). - - "Source: Standard table with character-like data type - DATA(stdtab_clike) = VALUE c50_tab_type( ( 'Hi' ) ( 'ABAP' ) ). - DATA xml_k TYPE xstring. - CALL TRANSFORMATION id SOURCE tab = stdtab_clike - RESULT XML xml_k. - - DATA(conv_xml_k) = cl_abap_conv_codepage=>create_in( )->convert( xml_k ). - out->write( `Source: Standard table with character-like data type` ). - out->write( format( conv_xml_k ) ). - out->write( |\n| ). - - "Source: Standard table with byte-like data type - DATA(stdtab_bytelike) = VALUE x30_tab_type( ( cl_abap_conv_codepage=>create_out( )->convert( `Hello` ) ) - ( cl_abap_conv_codepage=>create_out( )->convert( `ABAP` ) ) ). - DATA xml_l TYPE xstring. - CALL TRANSFORMATION id SOURCE xtab = stdtab_bytelike - RESULT XML xml_l. - - DATA(conv_xml_l) = cl_abap_conv_codepage=>create_in( )->convert( xml_l ). - out->write( `Source: Standard table with byte-like data type` ). - out->write( format( conv_xml_l ) ). - out->write( |\n| ). - - "Furthermore, some references to iXML and sXML libraries are possible. - "The following example covers sXML (an interface reference variable of type if_sxml_reader). - DATA(sxml_reader) = cl_sxml_string_reader=>create( xml_h ). - DATA xml_m TYPE xstring. - CALL TRANSFORMATION id SOURCE XML sxml_reader - RESULT XML xml_m. - - DATA(conv_xml_m) = cl_abap_conv_codepage=>create_in( )->convert( xml_m ). - out->write( `Source: Interface reference variable with TYPE REF TO if_sxml_reader` ). - out->write( format( conv_xml_m ) ). - out->write( |\n| ). - - out->write( `********** Source options for transforming ABAP data **********` ). - out->write( |\n| ). - "Using ... SOURCE ... without specifying XML - "One or multiple ABAP data objects can be specified. - - "Source: Data object of type string - "elem stands for the name of an XML element. - DATA(str_e) = `abcdef`. - DATA xml_n TYPE xstring. - CALL TRANSFORMATION id SOURCE elem = str_e - RESULT XML xml_n. - - DATA(conv_xml_n) = cl_abap_conv_codepage=>create_in( )->convert( xml_n ). - out->write( `Source: Character string in data object of type string` ). - out->write( format( conv_xml_n ) ). - out->write( |\n| ). - - "Source: Data object of type string - DATA(str_f) = `some string`. - DATA xml_o TYPE xstring. - CALL TRANSFORMATION id SOURCE txt = str_f - RESULT XML xml_o. - - DATA(conv_xml_o) = cl_abap_conv_codepage=>create_in( )->convert( xml_o ). - out->write( `Source: Character string of type string` ). - out->write( format( conv_xml_o ) ). - out->write( |\n| ). - - "Source: Multiple data objects - DATA a_i TYPE i VALUE 123. - DATA b_str TYPE string VALUE `Hallo`. - DATA c_p TYPE p LENGTH 5 DECIMALS 2 VALUE `4.56`. - DATA xml_p TYPE xstring. - - CALL TRANSFORMATION id SOURCE x = a_i - y = b_str - z = c_p - RESULT XML xml_p. - - DATA(conv_xml_p) = cl_abap_conv_codepage=>create_in( )->convert( xml_p ). - out->write( `Source: Multiple ABAP data objects in a static parameter list` ). - out->write( format( conv_xml_p ) ). - out->write( |\n| ). - - "Source: Dynamic specification of ABAP data objects in an internal table of - "type abap_trans_srcbind_tab - DATA(srctab) = VALUE abap_trans_srcbind_tab( - ( name = 'X' value = REF #( a_i ) ) - ( name = 'Y' value = REF #( b_str ) ) - ( name = 'Z' value = REF #( c_p ) ) ). - DATA xml_q TYPE xstring. - - CALL TRANSFORMATION id SOURCE (srctab) - RESULT XML xml_q. - - DATA(conv_xml_q) = cl_abap_conv_codepage=>create_in( )->convert( xml_q ). - out->write( `Source: Multiple ABAP data objects in an internal table` ). - out->write( format( conv_xml_q ) ). - -************************************************************************* - - out->write( zcl_demo_abap_aux=>heading( `21) CALL TRANSFORMATION Syntax: Results of Transformations` ) ). - "As in the examples above, the predefined identity transformation is used here. - - "Creating demo XML data to be used in the example as the source. - DATA(demo_xml) = cl_abap_conv_codepage=>create_out( )->convert( `Hi ABAP` ). - - out->write( `********** Result options for transforming to XML data ********** ` ). - out->write( |\n| ). - - "Result: Data object of type string - "The example uses the OPTIONS addition. The XML header should not be added. - DATA str_g TYPE string. - CALL TRANSFORMATION id SOURCE XML demo_xml - RESULT XML str_g - OPTIONS xml_header = 'NO'. - - out->write( `Result: Data object of type string` ). - out->write( str_g ). - out->write( |\n| ). - - "Data object of type xstring - DATA xml_r TYPE xstring. - CALL TRANSFORMATION id SOURCE XML demo_xml - RESULT XML xml_r. - - DATA(conv_xml_r) = cl_abap_conv_codepage=>create_in( )->convert( xml_r ). - out->write( `Result: Data object of type xstring` ). - out->write( format( conv_xml_r ) ). - out->write( |\n| ). - - "Data object declared inline (e.g. DATA(a) or FINAL(b)), which has then the type xstring - CALL TRANSFORMATION id SOURCE XML demo_xml - RESULT XML DATA(xml_s). - - DATA(conv_xml_s) = cl_abap_conv_codepage=>create_in( )->convert( xml_s ). - out->write( `Result: Data object declared inline (type xstring)` ). - out->write( format( conv_xml_s ) ). - out->write( |\n| ). - - "Standard table with character-like line type - DATA stdtab_clike_b TYPE c50_tab_type. - CALL TRANSFORMATION id SOURCE XML demo_xml - RESULT XML stdtab_clike_b - OPTIONS xml_header = 'NO'. - - out->write( `Result: Standard table with character-like line type` ). - out->write( stdtab_clike_b ). - out->write( |\n| ). - - "Standard table with byte-like line type - DATA stdtab_bytelike_b TYPE x30_tab_type. - CALL TRANSFORMATION id SOURCE XML demo_xml - RESULT XML stdtab_bytelike_b. - - out->write( `Result: Standard table with byte-like line type` ). - out->write( stdtab_bytelike_b ). - out->write( |\n| ). - - "Furthermore, some references to iXML and sXML libraries are possible. - "The following example covers sXML (an object reference variable of type ref to cl_sxml_string_writer) - "Other types are possible, for example JSON writers. - DATA(writer4tr) = cl_sxml_string_writer=>create( type = if_sxml=>co_xt_xml10 ). - CALL TRANSFORMATION id SOURCE XML demo_xml - RESULT XML writer4tr. - - DATA(xml_t) = writer4tr->get_output( ). - DATA(conv_xml_t) = cl_abap_conv_codepage=>create_in( )->convert( xml_t ). - out->write( `Result: Object reference variable with type ref to cl_sxml_string_writer` ). - out->write( format( conv_xml_t ) ). - out->write( |\n| ). - - out->write( `********** Result options for transforming to ABAP data **********` ). - out->write( |\n| ). - - "Similar to above, multiple ABAP data objects can be specified as a static parameter list. - "Here, the example from above is used. The tranformation is performed the other way round. - DATA d_i LIKE a_i. - DATA e_str LIKE b_str. - DATA f_p LIKE c_p. - - CALL TRANSFORMATION id SOURCE XML xml_p - RESULT x = d_i - y = e_str - z = f_p. - - out->write( `Result: Multiple ABAP data objects in a static parameter list` ). - out->write( d_i ). - out->write( e_str ). - out->write( f_p ). - out->write( |\n| ). - - "Specifying an internal table of type abap_trans_resbind_tab - DATA g_i LIKE a_i. - DATA h_str LIKE b_str. - DATA i_p LIKE c_p. - - "Note: Only bound parts are deserialized, i.e. the result table must be - "filled accordingly. - DATA(restab) = VALUE abap_trans_resbind_tab( - ( name = 'X' value = REF #( d_i ) ) - ( name = 'Y' value = REF #( e_str ) ) - ( name = 'Z' value = REF #( f_p ) ) ). - - CALL TRANSFORMATION id SOURCE XML xml_q - RESULT (restab). - - out->write( `Result: Multiple ABAP data objects in an internal table` ). - out->write( restab ). - -************************************************************************ - - out->write( zcl_demo_abap_aux=>heading( `22) Dealing with JSON Data` ) ). - "Note: When the identity transformation ID is used, the format is asJSON. - - "Elementary type - DATA str_h TYPE string VALUE `Hello`. - "ABAP -> JSON - "Creating a JSON writer - DATA(json_wr_a) = cl_sxml_string_writer=>create( type = if_sxml=>co_xt_json ). - - CALL TRANSFORMATION id SOURCE hi = str_h - RESULT XML json_wr_a. - - DATA(json_a) = cl_abap_conv_codepage=>create_in( )->convert( json_wr_a->get_output( ) ). - - out->write( `ABAP -> JSON: Elementary type` ). - out->write( json_a ). - out->write( |\n| ). - - "JSON -> ABAP - DATA str_i TYPE string. - "Note: CALL TRANSFORMATION handles JSON sources implicitly. - CALL TRANSFORMATION id SOURCE XML json_a - RESULT hi = str_i. - - out->write( `JSON -> ABAP: Elementary type` ). - out->write( str_i ). - out->write( |\n| ). - - "Structure - SELECT SINGLE carrid, carrname, currcode, url - FROM zdemo_abap_carr - WHERE carrid = 'AZ' - INTO @DATA(carr_struc_c). - - "ABAP -> JSON - DATA(json_wr_b) = cl_sxml_string_writer=>create( type = if_sxml=>co_xt_json ). - - CALL TRANSFORMATION id SOURCE structure = carr_struc_c - RESULT XML json_wr_b. - - DATA(json_b) = cl_abap_conv_codepage=>create_in( )->convert( json_wr_b->get_output( ) ). - out->write( `ABAP -> JSON: Structure` ). - out->write( json_b ). - out->write( |\n| ). - - "JSON -> ABAP - DATA carr_struc_d LIKE carr_struc_c. - CALL TRANSFORMATION id SOURCE XML json_b - RESULT structure = carr_struc_d. - - out->write( `JSON -> ABAP: Structure` ). - out->write( carr_struc_d ). - out->write( |\n| ). - - "Internal table - SELECT carrid, carrname, currcode, url - FROM zdemo_abap_carr - INTO TABLE @DATA(carr_tab_c) - UP TO 2 ROWS. - - "ABAP -> JSON - "This examples uses a cast to get access to further methods. - DATA(json_wr_c) = cl_sxml_string_writer=>create( type = if_sxml=>co_xt_json ). - DATA(json_wr_cast) = CAST if_sxml_writer( json_wr_c ). - - "With the following method calls, the result is formatted. - json_wr_cast->set_option( option = if_sxml_writer=>co_opt_linebreaks ). - json_wr_cast->set_option( option = if_sxml_writer=>co_opt_indent ). - - CALL TRANSFORMATION id SOURCE itab = carr_tab_c - RESULT XML json_wr_c. - - DATA(json_c) = cl_abap_conv_codepage=>create_in( )->convert( json_wr_c->get_output( ) ). - out->write( `ABAP -> JSON: Internal table` ). - out->write( json_c ). - out->write( |\n| ). - - "JSON -> ABAP - DATA carr_tab_d LIKE carr_tab_c. - - CALL TRANSFORMATION id SOURCE XML json_c - RESULT itab = carr_tab_d. - - out->write( `JSON -> ABAP: Internal table` ). - out->write( carr_tab_d ). - out->write( |\n| ). - - "JSON -> XML - DATA(str_j) = - `{` && - `"flights": [` && - ` {` && - ` "carrier": "LH",` && - ` "connectionid": "400",` && - ` "from": "Frankfurt",` && - ` "to": "Berlin"` && - ` },` && - ` {` && - ` "carrier": "DL",` && - ` "connectionid": "400",` && - ` "from": "San Francisco",` && - ` "to": "New York"` && - ` }` && - `]` && - `}`. - - DATA(json_d) = cl_abap_conv_codepage=>create_out( )->convert( str_j ). - DATA(json_wr_d) = cl_sxml_string_reader=>create( json_d ). - DATA json2xml_ct TYPE xstring. - - "JSON -> XML using CALL TRANSFORMATION - CALL TRANSFORMATION id SOURCE XML json_wr_d - RESULT XML json2xml_ct. - - DATA(conv_json2xml_ct) = cl_abap_conv_codepage=>create_in( )->convert( json2xml_ct ). - - out->write( `JSON -> XML using CALL TRANSFORMATION` ). - out->write( format( conv_json2xml_ct ) ). - out->write( |\n| ). - - "JSON -> XML using sXML - DATA(reader_a) = cl_sxml_string_reader=>create( cl_abap_conv_codepage=>create_out( - )->convert( str_j ) ). - "XML writer (note the type specification in contrast to the previous examples) - DATA(xml_wr) = cl_sxml_string_writer=>create( type = if_sxml=>co_xt_xml10 ). - - TRY. - reader_a->next_node( ). - "The reader parses the data in one go by calling the SKIP_NODE method. - "The data is passed to an XML writer. - reader_a->skip_node( xml_wr ). - CATCH cx_sxml_parse_error INTO DATA(err_pa). - out->write( err_pa->get_text( ) ). - ENDTRY. - - DATA(json2xml_sxml) = cl_abap_conv_codepage=>create_in( )->convert( xml_wr->get_output( ) ). - out->write( `JSON -> XML using sXML` ). - out->write( format( json2xml_sxml ) ). - out->write( |\n| ). - - "XML -> JSON using CALL TRANSFORMATION - DATA(json_wr_f) = cl_sxml_string_writer=>create( type = if_sxml=>co_xt_json ). - - CALL TRANSFORMATION id SOURCE XML json2xml_sxml - RESULT XML json_wr_f. - - DATA(xml2json_ct) = cl_abap_conv_codepage=>create_in( )->convert( json_wr_f->get_output( ) ). - out->write( `XML -> JSON using CALL TRANSFORMATION` ). - out->write( xml2json_ct ). - out->write( |\n| ). - - "XML -> JSON using sXML - DATA(reader_b) = cl_sxml_string_reader=>create( cl_abap_conv_codepage=>create_out( )->convert( xml2json_ct ) ). - DATA(json_wr) = cl_sxml_string_writer=>create( type = if_sxml=>co_xt_json ). - - TRY. - reader_b->next_node( ). - reader_b->skip_node( json_wr ). - CATCH cx_sxml_parse_error INTO DATA(err_xj). - out->write( err_xj->get_text( ) ). - ENDTRY. - - DATA(xml2json_sxml) = cl_abap_conv_codepage=>create_in( )->convert( json_wr->get_output( ) ). - out->write( `XML -> JSON using sXML` ). - out->write( xml2json_sxml ). - -************************************************************************ - - out->write( zcl_demo_abap_aux=>heading( `23) XCO Classes for JSON` ) ). - "Note: Unlike above, the following snippets do not work with asJSON as intermediate - "format. - - DATA: BEGIN OF carrier_struc, - carrier_id TYPE c length 3, - connection_id TYPE n length 4, - city_from TYPE c length 20, - city_to TYPE c length 20, - END OF carrier_struc. - - DATA carriers_tab like TABLE OF carrier_struc WITH EMPTY KEY. - - carrier_struc = VALUE #( carrier_id = 'AA' connection_id = '17' city_from = 'New York' city_to = 'San Francisco' ). - carriers_tab = VALUE #( ( carrier_id = 'AZ' connection_id = '788' city_from = 'Rome' city_to = 'Tokyo' ) - ( carrier_id = 'JL' connection_id = '408' city_from = 'Frankfurt' city_to = 'Tokyo' ) - ( carrier_id = 'LH' connection_id = '2402' city_from = 'Frankfurt' city_to = 'Berlin' ) ). - - "ABAP (structure) -> JSON using XCO - DATA(struc2json_xco) = xco_cp_json=>data->from_abap( carrier_struc )->to_string( ). - out->write( `ABAP (structure) -> JSON using XCO` ). - out->write( format( input = struc2json_xco xml = abap_false ) ). - out->write( |\n| ). - - "ABAP (internal table) -> JSON using XCO - DATA(itab2json_xco) = xco_cp_json=>data->from_abap( carriers_tab )->to_string( ). - out->write( `ABAP (internal table) -> JSON using XCO` ). - out->write( format( input = itab2json_xco xml = abap_false ) ). - out->write( |\n| ). - - "JSON -> ABAP (structure) using XCO - DATA json2struc_xco LIKE carrier_struc. - xco_cp_json=>data->from_string( struc2json_xco )->write_to( REF #( json2struc_xco ) ). - out->write( `JSON -> ABAP (structure) using XCO` ). - out->write( json2struc_xco ). - out->write( |\n| ). - - "JSON -> ABAP (internal table) using XCO - DATA json2itab_xco LIKE carriers_tab. - xco_cp_json=>data->from_string( itab2json_xco )->write_to( REF #( json2itab_xco ) ). - out->write( `JSON -> ABAP (internal table) using XCO` ). - out->write( json2itab_xco ). - out->write( |\n| ). - - "Creating JSON using XCO - "Check out more methods that offer more options to build the JSON by clicking - "CTRL + Space after '->' in ADT. - DATA(json_builder_xco) = xco_cp_json=>data->builder( ). - json_builder_xco->begin_object( - )->add_member( 'CarrierId' )->add_string( 'DL' - )->add_member( 'ConnectionId' )->add_string( '1984' - )->add_member( 'CityFrom' )->add_string( 'San Francisco' - )->add_member( 'CityTo' )->add_string( 'New York' - )->end_object( ). - - "Getting JSON data - DATA(json_created_xco) = json_builder_xco->get_data( )->to_string( ). - - out->write( `Creating JSON using XCO` ). - out->write( format( input = json_created_xco xml = abap_false ) ). - out->write( |\n| ). - - "Transforming the created JSON to ABAP (structure) - "Note: The JSON was intentionally created without the underscores in the - "name to demonstrate the 'apply' method. The following example demonstrates - "a transformation of camel case and underscore notation. As above, check out - "more options by clicking CTRL + Space after '...transformation->'. - CLEAR json2struc_xco. - xco_cp_json=>data->from_string( json_created_xco )->apply( VALUE #( - ( xco_cp_json=>transformation->pascal_case_to_underscore ) ) )->write_to( REF #( json2struc_xco ) ). - - out->write( `JSON -> ABAP (structure) using XCO demonstrating the apply method` ). - out->write( json2struc_xco ). - -************************************************************************ - - out->write( zcl_demo_abap_aux=>heading( `24) Excursion: Compressing and Decompressing Binary Data` ) ). - "You may want to process or store binary data. The data can be very large. - "You can compress the data in gzip format and decompress it for further processing using - "the cl_abap_gzip class. Check out appropriate exceptions to be caught. The simple example - "just specifies cx_root. See the class documentation for more information. - "This example uses a data object of type xstring from a previous example. - - "Compressing binary data - DATA xstr_comp TYPE xstring. - TRY. - cl_abap_gzip=>compress_binary( EXPORTING raw_in = xml_oref_a - IMPORTING gzip_out = xstr_comp ). - CATCH cx_root INTO DATA(error_comp). - out->write( error_comp->get_text( ) ). - ENDTRY. - - "Decompressing binary data - DATA xstr_decomp TYPE xstring. - TRY. - cl_abap_gzip=>decompress_binary( EXPORTING gzip_in = xstr_comp - IMPORTING raw_out = xstr_decomp ). - - CATCH cx_root INTO DATA(error_decomp). - out->write( error_decomp->get_text( ) ). - ENDTRY. - - "Checking the xstring length of the variables used and comparing the result - DATA(strlen_original_xstring) = xstrlen( xml_oref_a ). - out->write( |Length of original binary data object: { strlen_original_xstring }| ). - DATA(strlen_comp) = xstrlen( xstr_comp ). - out->write( |Length of compressed binary data object: { strlen_comp }| ). - DATA(strlen_decomp) = xstrlen( xstr_decomp ). - out->write( |Length of decompressed binary data object: { strlen_decomp }| ). - IF xml_oref_a = xstr_decomp. - out->write( `The decompressed binary data object has the same value as the original binary data object.` ). - ENDIF. - ENDMETHOD. - METHOD format. - TRY. - DATA(xstr) = cl_abap_conv_codepage=>create_out( )->convert( input ). - DATA(reader) = cl_sxml_string_reader=>create( xstr ). - DATA(writer) = CAST if_sxml_writer( cl_sxml_string_writer=>create( - type = COND #( WHEN xml = abap_true THEN if_sxml=>co_xt_xml10 ELSE if_sxml=>co_xt_json ) ) ). - writer->set_option( option = if_sxml_writer=>co_opt_linebreaks ). - writer->set_option( option = if_sxml_writer=>co_opt_indent ). - reader->next_node( ). - reader->skip_node( writer ). - string = cl_abap_conv_codepage=>create_in( )->convert( CAST cl_sxml_string_writer( writer )->get_output( ) ). - CATCH cx_root. - string = `Issue when formatting.`. - ENDTRY. - - ENDMETHOD. - - METHOD class_constructor. - "Filling demo database tables. - zcl_demo_abap_aux=>fill_dbtabs( ). - ENDMETHOD. - - METHOD concatenate_string. - attr_concat_string = attr_string_a && attr_string_b. - ENDMETHOD. - - METHOD deserialize_helper. - me->attr_string_a = attr_string_a. - me->attr_string_b = attr_string_b. - me->attr_concat_string = attr_concat_string. - ENDMETHOD. - - METHOD serialize_helper. - attr_string_a = me->attr_string_a. - attr_string_b = me->attr_string_b. - attr_concat_string = me->attr_concat_string. - ENDMETHOD. - - METHOD lowercase_string. - attr_lowercase_str = to_lower( attr_string_a && attr_string_b ). - ENDMETHOD. - +*********************************************************************** +* +* ABAP cheat sheet: Working with XML and JSON in ABAP +* +* -------------------------- PURPOSE ---------------------------------- +* - Example that demonstrates working with XML and JSON in ABAP. +* - The following topics are covered:* +* - Processing XML using class libraries (iXML, sXML) +* - XML Transformations using XSLT and Simple Transformations +* - CALL TRANSFORMATION syntax +* - Dealing with JSON data, XCO classes for JSON +* - Excursions: Converting string <-> xstring, compressing and +* decompressing binary data +* +* ----------------------- GETTING STARTED ----------------------------- +* - Open the class with the ABAP development tools for Eclipse (ADT). +* - Choose F9 to run the class. +* - Check the console output. +* - To understand the context and the ABAP syntax used, refer to the +* notes included in the class as comments or refer to the respective +* topic in the ABAP Keyword Documentation. +* - Due to the amount of console output, the examples contain numbers +* (e.g. 1) ..., 2) ..., 3) ...) for the individual example sections. +* Also, the variable name is displayed in most cases. So to find +* the relevant output in the console easier and faster, just search +* for the number/variable name in the console (CTRL+F in the console) +* or use the debugger. +* +* ----------------------------- NOTE ----------------------------------- +* The code presented in this class is intended only to support the ABAP +* cheat sheets. It is not intended for direct use in a production system +* environment. The code examples in the ABAP cheat sheets are primarily +* intended to provide a better explanation and visualization of the +* syntax and semantics of ABAP statements, not to solve concrete +* programming tasks. For production application programs, you should +* always work out your own solution for each individual case. There is +* no guarantee for the correctness or completeness of the code. +* Furthermore, there is no legal responsibility or liability for any +* errors or their consequences that may occur when using the the example +* code. +* +*********************************************************************** +"!

ABAP cheat sheet: Working with XML and JSON in ABAP

+"! Example that demonstrates working with XML and JSON in ABAP..
Choose F9 in ADT to run the class. +CLASS zcl_demo_abap_xml_json DEFINITION + PUBLIC + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + INTERFACES: if_oo_adt_classrun, + "This interface is implemented for serializing and + "deserialzing instances of classes (objects). + if_serializable_object. + CLASS-METHODS class_constructor. + + PROTECTED SECTION. + PRIVATE SECTION. + CLASS-METHODS format IMPORTING input TYPE data + xml TYPE abap_bool DEFAULT abap_true + RETURNING VALUE(string) TYPE string. + TYPES c50 TYPE c LENGTH 50. + TYPES c50_tab_type TYPE TABLE OF c50 WITH EMPTY KEY. + TYPES x30 TYPE x LENGTH 30. + TYPES x30_tab_type TYPE TABLE OF x30 WITH EMPTY KEY. + + "The following instance attribues and methods are used for serializing and + "deserialzing instances of classes (objects) + DATA: attr_string_a TYPE string, + attr_string_b TYPE string, + attr_concat_string TYPE string, + attr_lowercase_str TYPE string. + METHODS: concatenate_string, + lowercase_string, + "The following method can only have output parameters. + "For each output parameter of the serialize_helper method, you must specify + "an identically named input parameter of the deserialize_helper method + "with the same type. + serialize_helper EXPORTING attr_string_a TYPE string + attr_string_b TYPE string + attr_concat_string TYPE string, + "This method can only have input parameters. + deserialize_helper IMPORTING attr_string_a TYPE string + attr_string_b TYPE string + attr_concat_string TYPE string. +ENDCLASS. + + + +CLASS zcl_demo_abap_xml_json IMPLEMENTATION. + + METHOD if_oo_adt_classrun~main. + + out->write( |ABAP Cheat Sheet Example: Working with XML and JSON in ABAP\n\n| ). + out->write( |1) Excursion: Converting string <-> xstring| ). + "In the following examples, many operations are performed using binary data. + "This excursion shows the conversion of string to xstring and the other way round + "using a codepage. The examples use UTF-8. + "For this purpose, you can, for example, use the cl_abap_conv_codepage class + "and the XCO library. + + "Storing XML data in a data object of type string + DATA(xml_string) = + `` && + ` ` && + ` LH` && + ` 400` && + ` ` && + ` Frankfurt` && + ` FRA` && + ` ` && + ` ` && + ` ` && + ` Berlin` && + ` SXF` && + ` ` && + ` ` && + ` ` && + ` ` && + ` DL` && + ` 1984` && + ` ` && + ` San Francisco` && + ` SFO` && + ` ` && + ` ` && + ` ` && + ` New York` && + ` JFK` && + ` ` && + ` ` && + ` ` && + ``. + + "string -> xstring + "Note: UTF-8 is used by default. Here, it is specified explicitly. + "Conversion errors are caught using the cx_sy_conversion_codepage class. + TRY. + DATA(conv_xstring) = cl_abap_conv_codepage=>create_out( codepage = `UTF-8` )->convert( xml_string ). + CATCH cx_sy_conversion_codepage. + ENDTRY. + + "xstring -> string + DATA(conv_string) = cl_abap_conv_codepage=>create_in( )->convert( conv_xstring ). + + "As an alternative, you can use methods of the XCO library. + "string -> xstring + DATA(conv_xstring_xco) = xco_cp=>string( xml_string + )->as_xstring( xco_cp_character=>code_page->utf_8 + )->value. + + "xstring -> string + DATA(conv_string_xco) = xco_cp=>xstring( conv_xstring_xco + )->as_string( xco_cp_character=>code_page->utf_8 + )->value. + + conv_string = format( conv_string ). + conv_string_xco = format( conv_string_xco ). + out->write( |\n| ). + out->write( `Results of the xstring to string conversions:` ). + out->write( |\n| ). + out->write( conv_string ). + out->write( |\n| ). + out->write( conv_string_xco ). + +********************************************************************** + + out->write( zcl_demo_abap_aux=>heading( `2) Processing XML Using Class Libraries` ) ). + out->write( |Excursion: Usable iXML/sXML Classes and Interfaces\n\n| ). + "Using a released CDS view, classes and interfaces are retrieved that + "have 'ixml' and 'sxml' in the name for you to explore the released classes + "and interfaces in this context. + + SELECT ReleasedObjectType, ReleasedObjectName, ReleaseState + FROM i_apisforclouddevelopment + WHERE releasestate = 'RELEASED' + AND + ( ReleasedObjectType = 'CLAS' OR ReleasedObjectType = 'INTF' ) + AND + ( ReleasedObjectName LIKE '%IXML%' OR ReleasedObjectName LIKE '%SXML%' ) + INTO TABLE @DATA(released_xml_libs). + + out->write( `No output. You can check the internal table content in the debugger to view the usable artifacts.` ). + +*********************************************************************** + + out->write( zcl_demo_abap_aux=>heading( `3) Creating XML Data Using iXML` ) ). + "In the following example, XML data is created using the iXML library. + "This is done by creating DOM nodes step by step. The nodes are created as + "elements and attributes. Content is inserted into the XML data. + "The example uses an appropriate attribute setting so that the result + "represents XML data in asXML format. + "Note: You can check out more examples in the system by choosing CTRL + + "SHIFT + A in ADT and search for *demo_ixml*. + "For more information on the classes/methods used, check the documentation + "by choosing F2 in ADT when placing the cursor on a class/methods. + + "Creating one factory object of the access class cl_ixml_core using the + "create method. The object is used to access the iXML library. + DATA(ixml_cr) = cl_ixml_core=>create( ). + + "Creating a document + DATA(document_cr) = ixml_cr->create_document( ). + + "Step-by-step creation of DOM nodes + "Creating a root node + DATA(root) = document_cr->create_element_ns( name = 'abap' + prefix = 'asx' ). + root->set_attribute_ns( name = 'asx' + prefix = 'xmlns' + value = 'http://www.sap.com/abapxml' ). + root->set_attribute_ns( name = 'version' + value = '1.0' ). + document_cr->append_child( root ). + DATA(xml_node1) = document_cr->create_element_ns( prefix = 'asx' + name = 'values' ). + root->append_child( xml_node1 ). + DATA(xml_node2) = document_cr->create_element_ns( name = 'STRING' ). + xml_node1->append_child( xml_node2 ). + xml_node2->append_child( document_cr->create_text( 'Hello ABAP' ) ). + + "Creating a renderer (for rendering the XML document into the output stream) + DATA xml_doc TYPE xstring. + ixml_cr->create_renderer( document = document_cr + ostream = ixml_cr->create_stream_factory( )->create_ostream_xstring( string = xml_doc ) + )->render( ). + + "Getting XML data + DATA(xml_output) = format( cl_abap_conv_codepage=>create_in( )->convert( xml_doc ) ). + out->write( xml_output ). + +*********************************************************************** + + out->write( zcl_demo_abap_aux=>heading( `4) Parsing XML Data Using iXML` ) ). + "The example covers the following aspects: + "- Parsing XML data to a DOM object in one go + "- Directly reading nodes using various iXML methods + "- Directly reading nodes using element names + "- Reading using iterators, i.e. going over the XML nodes one after another + "- During the iteration, ... + " ... node properties are extracted using various iXML methods + " (and stored in an internal table for display purposes). + " ... the XML data is modified. + " ... a new element is created. + "- Rendering XML data + + "Internal table to store node properties for display purposes + DATA properties TYPE string_table. + + "Creating simple demo XML data to be used in the example + TRY. + DATA(some_xml) = cl_abap_conv_codepage=>create_out( )->convert( + `` && + ` hallo` && + ` how` && + ` are` && + `` ). + CATCH cx_sy_conversion_codepage. + ENDTRY. + + "Creating one factory object of the access class cl_ixml_core using the + "create method. It is used to access the iXML library. + DATA(ixml_pa) = cl_ixml_core=>create( ). + "Creaing an input stream that is used for the input of XML data + DATA(stream_factory_pa) = ixml_pa->create_stream_factory( ). + "Creating an XML document stored in DOM format in the memory + DATA(document_pa) = ixml_pa->create_document( ). + "Creating a parser + "It requires the following input parameters: input stream to be parsed, + "the XML document to which the stream is parsed, a factory required to create a stream + DATA(parser_pa) = ixml_pa->create_parser( + istream = stream_factory_pa->create_istream_xstring( string = some_xml ) + document = document_pa + stream_factory = stream_factory_pa ). + + "Parsing XML data to a DOM representation in one go. It is put in the memory. + "Note: You can also parse sequentially, and not in one go. + DATA(parsing_check) = parser_pa->parse( ). + IF parsing_check = 0. "Parsing was successful + + "Directly reading nodes using various iXML methods + + "Accessing the root element of the DOM. It can be used as the initial node + "for accessing subnodes. + "You can check the content of the variables in the debugger. + "Note: Multiple methods are available to further process the nodes. + DATA(root_element) = document_pa->get_root_element( ). + "First subnode + DATA(child_element) = root_element->get_first_child( ). + "Getting the value of that node + DATA(child_element_value) = child_element->get_value( ). + "Next adjacent node/getting the value + DATA(next_element_value) = child_element->get_next( )->get_value( ). + + "Directly reading nodes using element names + "The result is the first element searched for. + DATA(element_by_name) = document_pa->find_from_name( name = `word3` )->get_value( ). + "A lot more options are available such as access by attributes. + + "Reading using iterators, i.e. going over the XML nodes sequentially + + "Creating an iterator + DATA(iterator_pa) = document_pa->create_iterator( ). + DO. + "For the iteration, you can use the get_next method to process the nodes one after another. + "Note: Here, all nodes are respected. You can also create filters to go over specific nodes. + DATA(node_i) = iterator_pa->get_next( ). + IF node_i IS INITIAL. + EXIT. + ELSE. + "Extracting properties + "For display purposes, the properties are stored in an internal table. + APPEND |gid: { node_i->get_gid( ) } / type: { node_i->get_type( ) } / name: { node_i->get_name( ) } / value: { node_i->get_value( ) }| TO properties. + ENDIF. + + IF node_i->get_type( ) = if_ixml_node=>co_node_text. + "Modifying values + "Here, the values are capitalized. + node_i->set_value( to_upper( node_i->get_value( ) ) ). + ENDIF. + + "Creating a new element + IF node_i->get_value( ) = 'are'. + document_pa->create_simple_element_ns( name = 'word4' + value = 'you' + parent = node_i->get_parent( ) ). + ENDIF. + ENDDO. + + "Creating a renderer + DATA xml_pa TYPE xstring. + ixml_pa->create_renderer( document = document_pa + ostream = ixml_pa->create_stream_factory( )->create_ostream_xstring( string = xml_pa ) + )->render( ). + + "Getting XML + DATA(output_ixml_parsing) = format( cl_abap_conv_codepage=>create_in( )->convert( xml_pa ) ). + + out->write( output_ixml_parsing ). + out->write( |\n| ). + out->write( `Node properties:` ). + out->write( properties ). + ELSE. + out->write( `Parsing was not successful.` ). + ENDIF. + +*********************************************************************** + + out->write( zcl_demo_abap_aux=>heading( `5) Creating XML Data Using sXML (Token-Based Rendering)` ) ). + "For sXML, there are specialized writer classes, such as CL_SXML_STRING_WRITE. + "Writers created with this class render XML data to a byte string. + "The XML 1.0 format and UTF-8 are used by default in the create method. + "Here, the parameters are specified explicitly. + "Note: The interface IF_SXML_WRITER contains the components that are valid + "for all readers (the abstract superclass CL_SXML_WRITER includes this + "interface as well as implementations for all readers). In the example below, + "a cast is required so as to access special methods (such as open_element). + + DATA(writer) = CAST if_sxml_writer( cl_sxml_string_writer=>create( type = if_sxml=>co_xt_xml10 + encoding = 'UTF-8' ) ). + + TRY. + "Creating nodes (the order of the nodes is important) + writer->open_element( name = 'flights' ). + writer->open_element( name = 'flight' ). + writer->open_element( name = 'carrier' ). + writer->write_value( 'LH' ). + writer->close_element( ). + writer->open_element( name = 'flightnumber' ). + writer->write_value( '400' ). + writer->close_element( ). + writer->close_element( ). + writer->open_element( name = 'flight' ). + writer->open_element( name = 'carrier' ). + writer->write_value( 'DL' ). + writer->close_element( ). + writer->open_element( name = 'flightnumber' ). + writer->write_value( '1984' ). + writer->close_element( ). + writer->close_element( ). + writer->close_element( ). + CATCH cx_sxml_state_error INTO DATA(error_token). + out->write( error_token->get_text( ) ). + ENDTRY. + + "Getting XML data + "The XML data can be retrieved with the GET_OUTPUT method. + "Also here, a cast is required. The result is of type xstring. + DATA(xml_sxml) = CAST cl_sxml_string_writer( writer )->get_output( ). + + DATA(output_sxml_token_rendering) = format( cl_abap_conv_codepage=>create_in( )->convert( xml_sxml ) ). + out->write( output_sxml_token_rendering ). + +*********************************************************************** + + out->write( zcl_demo_abap_aux=>heading( `6) Creating XML Data using sXML (Object-Oriented Rendering)` ) ). + + DATA(writer_oo) = CAST if_sxml_writer( cl_sxml_string_writer=>create( type = if_sxml=>co_xt_xml10 + encoding = 'UTF-8' ) ). + + TRY. + writer_oo->write_node( writer_oo->new_open_element( name = 'flights' ) ). + + writer_oo->write_node( writer_oo->new_open_element( name = 'flight' ) ). + writer_oo->write_node( writer_oo->new_open_element( name = 'carrier' ) ). + DATA(val) = writer_oo->new_value( ). + val->set_value( 'AZ' ). + writer_oo->write_node( val ). + writer_oo->write_node( writer_oo->new_close_element( ) ). + writer_oo->write_node( writer_oo->new_open_element( name = 'flightnumber' ) ). + val = writer_oo->new_value( ). + val->set_value( '788' ). + writer_oo->write_node( val ). + writer_oo->write_node( writer_oo->new_close_element( ) ). + writer_oo->write_node( writer_oo->new_close_element( ) ). + + writer_oo->write_node( writer_oo->new_open_element( name = 'flight' ) ). + writer_oo->write_node( writer_oo->new_open_element( name = 'carrier' ) ). + val = writer_oo->new_value( ). + val->set_value( 'JL' ). + writer_oo->write_node( val ). + writer_oo->write_node( writer_oo->new_close_element( ) ). + writer_oo->write_node( writer_oo->new_open_element( name = 'flightnumber' ) ). + val = writer_oo->new_value( ). + val->set_value( '407' ). + writer_oo->write_node( val ). + writer_oo->write_node( writer_oo->new_close_element( ) ). + writer_oo->write_node( writer_oo->new_close_element( ) ). + + writer_oo->write_node( writer_oo->new_close_element( ) ). + CATCH cx_sxml_state_error INTO DATA(error_oo). + out->write( error_oo->get_text( ) ). + ENDTRY. + + DATA(xml_sxml_oo_rendering) = CAST cl_sxml_string_writer( writer_oo )->get_output( ). + + DATA(output_sxml_oo_rendering) = format( cl_abap_conv_codepage=>create_in( )->convert( xml_sxml_oo_rendering ) ). + out->write( output_sxml_oo_rendering ). + +*********************************************************************** + + out->write( zcl_demo_abap_aux=>heading( `7) Parsing XML Data using sXML (Token-Based Parsing)` ) ). + + "Creating demo XML data to be used in the example + TRY. + DATA(xml_to_parse) = cl_abap_conv_codepage=>create_out( )->convert( + `` && + `` && + ` ` && + ` A` && + ` 01-01-2024` && + ` ` && + ` ` && + ` abc` && + ` def` && + ` ghi` && + ` jkl` && + ` ` && + `` ). + CATCH cx_sy_conversion_codepage. + ENDTRY. + + "Creating an internal table for display purposes + DATA: BEGIN OF node_info, + node_type TYPE string, + prefix TYPE string, + name TYPE string, + nsuri TYPE string, + value_type TYPE string, + value TYPE string, + value_raw TYPE xstring, + END OF node_info, + nodes_tab LIKE TABLE OF node_info. + + "Creating reader + "Note: See the comments for the writer above which is similar. For readers, + "the interface IF_SXML_READER exists. In this example, no special methods + "are used. Therefore, a cast is not carried out. + DATA(reader) = cl_sxml_string_reader=>create( xml_to_parse ). + "DATA(reader_cast) = CAST if_sxml_reader( cl_sxml_string_reader=>create( xml_oo ) ). + + "To iterate accros all nodes, you can call the NEXT_NODE method. + TRY. + DO. + "Check out other available methods in ADT by placing the cursor behind -> + "and choosing CTRL + Space. + reader->next_node( ). + + "When reaching the end of the XML data, the loop is exited. + IF reader->node_type = if_sxml_node=>co_nt_final. + EXIT. + ENDIF. + + "You can access the properties of the node directly. + "For display purposes, the property information is stored in an internal table. + "The demo XML data that is used here does not include all properties. Therefore, + "the values for these are initial. + + "Node type, see the interface if_sxml_node + DATA(node_type) = SWITCH #( reader->node_type WHEN if_sxml_node=>co_nt_initial THEN `CO_NT_INITIAL` + WHEN if_sxml_node=>co_nt_element_open THEN `CO_NT_ELEMENT_OPEN` + WHEN if_sxml_node=>co_nt_element_close THEN `CO_NT_ELEMENT_CLOSE` + WHEN if_sxml_node=>co_nt_value THEN `CO_NT_VALUE` + WHEN if_sxml_node=>co_nt_attribute THEN `CO_NT_ATTRIBUTE` + ELSE `Error` ). + + DATA(prefix) = reader->prefix. "Namespace prefix + DATA(name) = reader->name. "Name of the element + DATA(nsuri) = reader->nsuri. "Namespace URI + + "Value type, see the interface if_sxml_value + DATA(value_type) = SWITCH #( reader->value_type WHEN 0 THEN `Initial` + WHEN if_sxml_value=>co_vt_none THEN `CO_VT_NONE` + WHEN if_sxml_value=>co_vt_text THEN `CO_VT_TEXT` + WHEN if_sxml_value=>co_vt_raw THEN `CO_VT_RAW` + WHEN if_sxml_value=>co_vt_any THEN `CO_VT_ANY` + ELSE `Error` ). + + DATA(value) = reader->value. "Character-like value (if it is textual data) + DATA(value_raw) = reader->value_raw. "Byte-like value (if it is raw data) + + APPEND VALUE #( node_type = node_type + prefix = prefix + name = name + nsuri = nsuri + value_type = value_type + value = value + value_raw = value_raw ) TO nodes_tab. + + "Once the method is called, you can directly access the attributes of the reader with the required + "properties of the node. When the parser is on the node of an element opening, you can use the method + "NEXT_ATTRIBUTE to iterate across the XML element attributes. + 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 = `attribute` + prefix = reader->prefix + name = reader->name + nsuri = reader->nsuri + value = reader->value + value_raw = reader->value_raw ) TO nodes_tab. + ENDDO. + ENDIF. + ENDDO. + CATCH cx_sxml_state_error INTO DATA(error_parse_token). + out->write( error_parse_token->get_text( ) ). + ENDTRY. + + out->write( `Node properties:` ). + out->write( nodes_tab ). + +*********************************************************************** + + out->write( zcl_demo_abap_aux=>heading( `8) Parsing XML Data using sXML (Object-Oriented Parsing)` ) ). + + CLEAR nodes_tab. + DATA(reader_oo) = cl_sxml_string_reader=>create( xml_to_parse ). + + TRY. + DO. + "To iterate accros all nodes, you can call the READ_NEXT_NODE method. + "When the end of the XML data is reached, the returned value is initial. + DATA(node_oo) = reader_oo->read_next_node( ). + IF node_oo IS INITIAL. + EXIT. + ENDIF. + + "In object-oriented parsing, methods for token-based parsing are wrapped. + "An object-oriented access to the node is provided. + "References to objects that represent the current node are returned. + + "Getting the node type + DATA(n_type) = node_oo->type. + + "If the parser is currently on the node of an element opening, + "the node object has the class CL_SXML_OPEN_ELEMENT that implements the + "interface IF_SXML_OPEN_ELEMENT. With the methods included, you can + "access the XML attributes of the element, e.g. using the GET_ATTRIBUTES + "method to put the references for all attributes into an internal table. + "To access the attributes, a downcast is required. + + CASE n_type. + WHEN if_sxml_node=>co_nt_element_open. + DATA(open_element) = CAST if_sxml_open_element( node_oo ). + + APPEND VALUE #( node_type = `open element` + prefix = open_element->prefix + name = open_element->qname-name + nsuri = open_element->qname-namespace + ) TO nodes_tab. + + DATA(attributes) = open_element->get_attributes( ). + + LOOP AT attributes INTO DATA(attribute). + APPEND VALUE #( node_type = `attribute` + prefix = open_element->prefix + name = open_element->qname-name + nsuri = open_element->qname-namespace + value = SWITCH #( attribute->value_type WHEN if_sxml_value=>co_vt_text THEN attribute->get_value( ) ) + value_raw = SWITCH #( attribute->value_type WHEN if_sxml_value=>co_vt_raw THEN attribute->get_value_raw( ) ) + ) TO nodes_tab. + ENDLOOP. + + WHEN if_sxml_node=>co_nt_element_close. + DATA(close_element) = CAST if_sxml_close_element( node_oo ). + + APPEND VALUE #( node_type = `close element` + prefix = open_element->prefix + name = open_element->qname-name + nsuri = open_element->qname-namespace + ) TO nodes_tab. + + WHEN if_sxml_node=>co_nt_value. + DATA(value_node_oo) = CAST if_sxml_value_node( node_oo ). + + APPEND VALUE #( node_type = `value` + value = SWITCH #( value_node_oo->value_type WHEN if_sxml_value=>co_vt_text THEN value_node_oo->get_value( ) ) + value_raw = SWITCH #( value_node_oo->value_type WHEN if_sxml_value=>co_vt_raw THEN value_node_oo->get_value_raw( ) ) + ) TO nodes_tab. + + WHEN OTHERS. + APPEND VALUE #( node_type = `Error` ) TO nodes_tab. + ENDCASE. + ENDDO. + CATCH cx_sxml_state_error INTO DATA(error_parse_oo). + out->write( error_parse_oo->get_text( ) ). + ENDTRY. + + out->write( `Node properties:` ). + out->write( nodes_tab ). + +*********************************************************************** + + out->write( zcl_demo_abap_aux=>heading( `XML Transformations` ) ). + + out->write( |9) Excursion: Available ABAP Cheat Sheet Transformations in the System\n\n| ). + "Excursion using the XCO library. In this example, tranformation programs are retrieved. + "A filter is applied. Because of a filter that is applied, only the ABAP cheat sheet + "transformation programs are returned. + + DATA(filter) = xco_cp_abap_repository=>object_name->get_filter( + xco_cp_abap_sql=>constraint->contains_pattern( 'ZDEMO_ABAP_%' ) ). + + DATA(filtered_transformations) = xco_cp_abap_repository=>objects->xslt->where( VALUE #( ( filter ) + ) )->in( xco_cp_abap=>repository )->get( ). + + IF filtered_transformations IS NOT INITIAL. + TYPES cst TYPE TABLE OF sxco_tf_object_name WITH EMPTY KEY. + DATA(cheat_sheet_transformations) = VALUE cst( FOR tr IN filtered_transformations ( tr->name ) ). + out->write( cheat_sheet_transformations ). + out->write( |\n| ). + out->write( `The code contains an implementation that gets all the transformations in the system.` ). + out->write( `You can check the content of the variable in the debugger. Among the transformations is the predefined identity transformation ID.` ). + ENDIF. + + "Getting all transformations in the system + "You can check the table content in the debugger. + DATA(all_transformations) = xco_cp_abap_repository=>objects->xslt->all->in( xco_cp_abap=>repository )->get( ). + IF all_transformations IS NOT INITIAL. + DATA(all_transformations_in_system) = VALUE cst( FOR tr IN all_transformations ( tr->name ) ). + ENDIF. + +*********************************************************************** + + out->write( zcl_demo_abap_aux=>heading( `10) Transforming XML to XML Using XSLT` ) ). + "In this example, XML is transformed to XML. For this purpose, a simple XSLT + "program does the following: + "- All nodes and attributes are copied from the source XML to the target XML + " without any changes. + "- A match on two elements is performed. If matched, two new elements are created + " in the target XML. In this operation, calculations are carried out (free seats + " and the occupancy rate based on the values of maximum and occupied seats). + "Note: + "- The element names in the demo XML data are capitalized on purpose because the + " XML data is used in another example that uses the asXML format. In deserializations + " of XML data to ABAP data, the elements that are deserialized must be capitalized + " so that they can be identified. + "Tranformations are performed using CALL TRANSFORMATION statements. + + "Creating demo XML data to be used in the example + TRY. + DATA(xml_flights) = cl_abap_conv_codepage=>create_out( codepage = `UTF-8` )->convert( + `` && + ` ` && + ` AA` && + ` 17` && + ` 385` && + ` 369` && + ` ` && + ` ` && + ` LH` && + ` 400` && + ` 330` && + ` 319` && + ` ` && + `` ). + CATCH cx_sy_conversion_codepage. + ENDTRY. + + DATA xml_a TYPE xstring. + + CALL TRANSFORMATION zdemo_abap_xslt_fl + SOURCE XML xml_flights + RESULT XML xml_a. + + DATA(conv_xml_a) = format( cl_abap_conv_codepage=>create_in( )->convert( xml_a ) ). + out->write( conv_xml_a ). + +*********************************************************************** + + out->write( zcl_demo_abap_aux=>heading( `11) Transforming ABAP to XML Using XSLT` ) ). + "In the example, data entries are retrieved from a database table. Appropriate names for the + "table columns are used with the AS addition so that the transformation can be carried + "out based on the selected data. + "Note: The resulting XML has the asXML format. + + SELECT carrid AS carrier, + connid AS connectionid, + seatsmax AS maxSeats, + seatsocc AS occSeats + FROM zdemo_abap_fli + WHERE carrid = 'AZ' + INTO TABLE @DATA(fli_itab) + UP TO 2 ROWS. + + DATA xml_b TYPE xstring. + + CALL TRANSFORMATION zdemo_abap_xslt_fl + SOURCE flights = fli_itab + RESULT XML xml_b. + + DATA(conv_xml_b) = format( cl_abap_conv_codepage=>create_in( )->convert( xml_b ) ). + out->write( conv_xml_b ). + +*********************************************************************** + + out->write( zcl_demo_abap_aux=>heading( `12) ABAP <-> XML using Simple Transformations (1)` ) ). + "The following simple transformation examples transform ABAP to XML and back. The + "Simple Transformation is implemented in a way to transform to the HTML format. + "This example transforms string tables to html. + + DATA(string_table_a) = VALUE string_table( ( `abc` ) ( `def` ) ( `ghi` ) ). + + DATA xml_c TYPE xstring. + + "ABAP -> XML + CALL TRANSFORMATION zdemo_abap_st_strhtml + SOURCE string_table = string_table_a + RESULT XML xml_c. + + DATA(conv_xml_c) = format( cl_abap_conv_codepage=>create_in( )->convert( xml_c ) ). + out->write( `ABAP -> XML` ). + out->write( conv_xml_c ). + out->write( |\n| ). + + "XML -> ABAP + DATA string_table_b TYPE string_table. + CALL TRANSFORMATION zdemo_abap_st_strhtml + SOURCE XML xml_c + RESULT string_table = string_table_b. + + out->write( `XML -> ABAP` ). + out->write( string_table_b ). + +*********************************************************************** + + out->write( zcl_demo_abap_aux=>heading( `13) ABAP <-> XML using Simple Transformations (2)` ) ). + "In this example, an internal table is transformed to XML using Simple Transformation. + "HTML tags are inserted into the XML data as literals. + + SELECT carrid, carrname, currcode, url + FROM zdemo_abap_carr + INTO TABLE @DATA(carr_tab_a) + UP TO 2 ROWS. + + "ABAP -> XML + DATA str_a TYPE string. + + "The following CALL TRANSFORMATION statement includes the OPTIONS + "addition. In this example, the XML header should not be added. + "So, you can take the resulting html and test it in an HTML viewer. + + CALL TRANSFORMATION zdemo_abap_st_carrhtml + SOURCE carrier_info = carr_tab_a + RESULT XML str_a + OPTIONS xml_header = 'NO'. + + out->write( `ABAP -> XML` ). + out->write( format( str_a ) ). + out->write( |\n| ). + + "XML -> ABAP + DATA carr_tab_b LIKE carr_tab_a. + + CALL TRANSFORMATION zdemo_abap_st_carrhtml + SOURCE XML str_a + RESULT carrier_info = carr_tab_b. + + out->write( `XML -> ABAP` ). + out->write( carr_tab_b ). + +*********************************************************************** + + out->write( zcl_demo_abap_aux=>heading( `ABAP <-> XML using XSLT (Using the Predefined Identity Transformation ID)` ) ). + "The following examples demonstrate serializations (ABAP to XML) and deserializations (XML to ABAP) + "using the predefined identity transformation ID. + "Note: In doing so, ABAP data is transformed to their asXML representations that can be used as an + " intermediate format and which define a mapping between ABAP data and XML. + + out->write( |14) Elementary type\n\n| ). + "The example uses type string as an elementary type. + + "ABAP -> XML + DATA xml_d TYPE xstring. + DATA(str_b) = `This is some string.`. + + CALL TRANSFORMATION id SOURCE txt = str_b + RESULT XML xml_d. + + DATA(conv_xml_d) = cl_abap_conv_codepage=>create_in( )->convert( xml_d ). + out->write( `ABAP -> XML` ). + out->write( format( conv_xml_d ) ). + out->write( |\n| ). + + "XML -> ABAP + DATA str_c TYPE string. + CALL TRANSFORMATION id SOURCE XML xml_d + RESULT txt = str_c. + + out->write( `XML -> ABAP` ). + out->write( str_c ). + +************************************************************************ + + out->write( zcl_demo_abap_aux=>heading( `15) Structures` ) ). + + SELECT SINGLE carrid, carrname, currcode, url + FROM zdemo_abap_carr + WHERE carrid = 'LH' + INTO @DATA(carr_struc_a). + + "ABAP -> XML + DATA xml_e TYPE xstring. + CALL TRANSFORMATION id SOURCE structure = carr_struc_a + RESULT XML xml_e. + + DATA(conv_xml_e) = cl_abap_conv_codepage=>create_in( )->convert( xml_e ). + out->write( `ABAP -> XML` ). + out->write( format( conv_xml_e ) ). + out->write( |\n| ). + + "XML -> ABAP + DATA carr_struc_b LIKE carr_struc_a. + CALL TRANSFORMATION id SOURCE XML xml_e + RESULT structure = carr_struc_b. + + out->write( `XML -> ABAP` ). + out->write( carr_struc_b ). + out->write( |\n| ). + +************************************************************************ + + out->write( zcl_demo_abap_aux=>heading( `16) Internal tables` ) ). + + SELECT carrid, connid, fldate, price, currency + FROM zdemo_abap_fli + WHERE carrid = 'JL' + INTO TABLE @DATA(fli_tab_a) + UP TO 2 ROWS. + + "ABAP -> XML + DATA xml_f TYPE xstring. + CALL TRANSFORMATION id SOURCE itab = fli_tab_a + RESULT XML xml_f. + + DATA(conv_xml_f) = cl_abap_conv_codepage=>create_in( )->convert( xml_f ). + out->write( `ABAP -> XML` ). + out->write( format( conv_xml_f ) ). + out->write( |\n| ). + + "XML -> ABAP + DATA fli_tab_b LIKE fli_tab_a. + CALL TRANSFORMATION id SOURCE XML xml_f + RESULT itab = fli_tab_b. + + out->write( `XML -> ABAP` ). + out->write( fli_tab_b ). + +************************************************************************ + + out->write( zcl_demo_abap_aux=>heading( `17) Data References` ) ). + + DATA(dref_a) = NEW i( 123 ). + + "ABAP -> XML + DATA xml_g TYPE xstring. + CALL TRANSFORMATION id SOURCE dref = dref_a + RESULT XML xml_g. + + DATA(conv_xml_g) = cl_abap_conv_codepage=>create_in( )->convert( xml_g ). + + out->write( `ABAP -> XML` ). + out->write( format( conv_xml_g ) ). + out->write( |\n| ). + + "XML -> ABAP + DATA dref_b LIKE dref_a. + CALL TRANSFORMATION id SOURCE XML xml_g + RESULT dref = dref_b. + + out->write( `XML -> ABAP` ). + out->write( dref_b->* ). + +************************************************************************ + + out->write( zcl_demo_abap_aux=>heading( `18) Object References` ) ). + "The following example demonstrates the serialization and deserialization of + "instances of classes (objects). For example, to serialize instance attributes, + "classes must implement the if_serializable_object interface. By default, all instance + "attributes of an object are serialized, regardless of their visibility section. + "However, you can change this behavior using the serialize_helper and deserialize_helper + "instance methods. As a result of the transformation, you get an asXML representation of + "the object. + "The example is implemented as follows: + "- The class implements the if_serializable_object interface. + "- There are 4 instance attributes of type string. + "- There are two instance methods: + " - One method concatenates two of the strings and assigns the resulting string to + " another string. + " - Another method concatenates two strings and converts the string to lowercase. + " The result is assigned to another string. + "- Serialization preserves instance attribute values in the asXML representation of the + " object. + "- During deserialization, the instance attribute values are transformed back and can + " be accessed. + "- The example includes the implementation of the serialize_helper and deserialize_helper + " instance methods. Without implementation, all instance attributes would be + " serialized/deserialized. The sample implementation limits serialization/deserialization. + " The fourth instance attribute, which is converted to a lowercase string when calling the + " method, is not part of the serialization/deserialization. See the implementation of the + " serialize_helper and deserialize_helper instance methods. They explicitly specify what + " to serialize and deserialize. + "- Note: For each output parameter of the serialize_helper method, you must specify an + " identically-named input parameter of the deserialize_helper method. The parameters must + " have the same type. + + DATA(oref_a) = NEW zcl_demo_abap_xml_json( ). + oref_a->attr_string_a = `AB`. + oref_a->attr_string_b = `AP`. + oref_a->concatenate_string( ). + oref_a->lowercase_string( ). + + out->write( `Value of instance attribute attr_lowercase_str for the created instance (before serialization/deserialization):` ). + out->write( oref_a->attr_lowercase_str ). + out->write( |\n| ). + + "ABAP -> XML + DATA xml_oref_a TYPE xstring. + CALL TRANSFORMATION id SOURCE oref = oref_a + RESULT XML xml_oref_a. + + DATA(conv_xml_oref_a) = cl_abap_conv_codepage=>create_in( )->convert( xml_oref_a ). + + out->write( `ABAP -> XML` ). + out->write( format( conv_xml_oref_a ) ). + out->write( |\n| ). + + "XML -> ABAP + DATA oref_b LIKE oref_a. + CALL TRANSFORMATION id SOURCE XML xml_oref_a + RESULT oref = oref_b. + + out->write( `XML -> ABAP` ). + out->write( oref_b->attr_string_a ). + out->write( oref_b->attr_string_b ). + out->write( oref_b->attr_concat_string ). + out->write( |\n| ). + IF oref_b->attr_lowercase_str IS INITIAL. + out->write( `The instance attribute attr_lowercase_str is initial. The serialization/deserialization is restricted.` ). + ENDIF. + +************************************************************************ + + out->write( zcl_demo_abap_aux=>heading( `19) CALL TRANSFORMATION Syntax: Specifying Transformations` ) ). + "As already covered in the examples above, transformations are specified after + "CALL TRANSFORMATION. They are either ... + + "... XSLT programs + CALL TRANSFORMATION zdemo_abap_st_carrhtml SOURCE carrier_info = carr_tab_a + RESULT XML str_a. + + "... predefined identity transformations + CALL TRANSFORMATION id SOURCE dref = dref_a + RESULT XML xml_g. + + "... dynamically specified transformation (valid for both XSLT and ST). In the examples above, + "the transformation is specified statically. Dynamic specifications are possible. A + "character-like data object in uppercase letters is expected in parentheses (either a named + "or unnamed data objects). + CALL TRANSFORMATION ('ID') SOURCE dref = dref_a + RESULT XML xml_g. + + "If a dynamically specified transformation is not found, an exception of the class + "CX_INVALID_TRANSFORMATION is raied. The example uses a named data object. + DATA(notr) = 'NON_EXISTENT_TRANSFORMATION'. + TRY. + CALL TRANSFORMATION (notr) SOURCE dref = dref_a + RESULT XML xml_g. + CATCH cx_invalid_transformation INTO DATA(error_non). + out->write( error_non->get_text( ) ). + ENDTRY. + + "... Simple Transformation + CALL TRANSFORMATION zdemo_abap_st_carrhtml SOURCE XML str_a + RESULT carrier_info = carr_tab_b. + +************************************************************************ + + out->write( zcl_demo_abap_aux=>heading( `20) CALL TRANSFORMATION Syntax: Sources of Transformations` ) ). + "The following examples use the predefined identity transformation ID. + "The result is asXML data and stored in a variable of type xstring. + "Multiple options and variants are possible. The examples cover a selection. + + out->write( `********** Source options for transforming XML data **********` ). + out->write( |\n| ). + + "Source: XML data in a data object of type string. It is implicitly transformed to + "XML in this case. + "Note: It must have character-like XML data in XML 1.0 format. + DATA(str_d) = `Hello world`. + DATA xml_h TYPE xstring. + CALL TRANSFORMATION id SOURCE XML str_d + RESULT XML xml_h. + + DATA(conv_xml_h) = cl_abap_conv_codepage=>create_in( )->convert( xml_h ). + + out->write( `Source: XML data in data object of type string` ). + out->write( format( conv_xml_h ) ). + out->write( |\n| ). + + "Source: XML data in a data object of type xstring + DATA(xml_i) = cl_abap_conv_codepage=>create_out( )->convert( `Hi ABAP` ). + DATA xml_j TYPE xstring. + CALL TRANSFORMATION id SOURCE XML xml_i + RESULT XML xml_j. + + DATA(conv_xml_j) = cl_abap_conv_codepage=>create_in( )->convert( xml_j ). + out->write( `Source: XML data in a data object of type xstring` ). + out->write( format( conv_xml_j ) ). + out->write( |\n| ). + + "Source: Standard table with character-like data type + DATA(stdtab_clike) = VALUE c50_tab_type( ( 'Hi' ) ( 'ABAP' ) ). + DATA xml_k TYPE xstring. + CALL TRANSFORMATION id SOURCE tab = stdtab_clike + RESULT XML xml_k. + + DATA(conv_xml_k) = cl_abap_conv_codepage=>create_in( )->convert( xml_k ). + out->write( `Source: Standard table with character-like data type` ). + out->write( format( conv_xml_k ) ). + out->write( |\n| ). + + "Source: Standard table with byte-like data type + DATA(stdtab_bytelike) = VALUE x30_tab_type( ( cl_abap_conv_codepage=>create_out( )->convert( `Hello` ) ) + ( cl_abap_conv_codepage=>create_out( )->convert( `ABAP` ) ) ). + DATA xml_l TYPE xstring. + CALL TRANSFORMATION id SOURCE xtab = stdtab_bytelike + RESULT XML xml_l. + + DATA(conv_xml_l) = cl_abap_conv_codepage=>create_in( )->convert( xml_l ). + out->write( `Source: Standard table with byte-like data type` ). + out->write( format( conv_xml_l ) ). + out->write( |\n| ). + + "Furthermore, some references to iXML and sXML libraries are possible. + "The following example covers sXML (an interface reference variable of type if_sxml_reader). + DATA(sxml_reader) = cl_sxml_string_reader=>create( xml_h ). + DATA xml_m TYPE xstring. + CALL TRANSFORMATION id SOURCE XML sxml_reader + RESULT XML xml_m. + + DATA(conv_xml_m) = cl_abap_conv_codepage=>create_in( )->convert( xml_m ). + out->write( `Source: Interface reference variable with TYPE REF TO if_sxml_reader` ). + out->write( format( conv_xml_m ) ). + out->write( |\n| ). + + out->write( `********** Source options for transforming ABAP data **********` ). + out->write( |\n| ). + "Using ... SOURCE ... without specifying XML + "One or multiple ABAP data objects can be specified. + + "Source: Data object of type string + "elem stands for the name of an XML element. + DATA(str_e) = `abcdef`. + DATA xml_n TYPE xstring. + CALL TRANSFORMATION id SOURCE elem = str_e + RESULT XML xml_n. + + DATA(conv_xml_n) = cl_abap_conv_codepage=>create_in( )->convert( xml_n ). + out->write( `Source: Character string in data object of type string` ). + out->write( format( conv_xml_n ) ). + out->write( |\n| ). + + "Source: Data object of type string + DATA(str_f) = `some string`. + DATA xml_o TYPE xstring. + CALL TRANSFORMATION id SOURCE txt = str_f + RESULT XML xml_o. + + DATA(conv_xml_o) = cl_abap_conv_codepage=>create_in( )->convert( xml_o ). + out->write( `Source: Character string of type string` ). + out->write( format( conv_xml_o ) ). + out->write( |\n| ). + + "Source: Multiple data objects + DATA a_i TYPE i VALUE 123. + DATA b_str TYPE string VALUE `Hallo`. + DATA c_p TYPE p LENGTH 5 DECIMALS 2 VALUE `4.56`. + DATA xml_p TYPE xstring. + + CALL TRANSFORMATION id SOURCE x = a_i + y = b_str + z = c_p + RESULT XML xml_p. + + DATA(conv_xml_p) = cl_abap_conv_codepage=>create_in( )->convert( xml_p ). + out->write( `Source: Multiple ABAP data objects in a static parameter list` ). + out->write( format( conv_xml_p ) ). + out->write( |\n| ). + + "Source: Dynamic specification of ABAP data objects in an internal table of + "type abap_trans_srcbind_tab + DATA(srctab) = VALUE abap_trans_srcbind_tab( + ( name = 'X' value = REF #( a_i ) ) + ( name = 'Y' value = REF #( b_str ) ) + ( name = 'Z' value = REF #( c_p ) ) ). + DATA xml_q TYPE xstring. + + CALL TRANSFORMATION id SOURCE (srctab) + RESULT XML xml_q. + + DATA(conv_xml_q) = cl_abap_conv_codepage=>create_in( )->convert( xml_q ). + out->write( `Source: Multiple ABAP data objects in an internal table` ). + out->write( format( conv_xml_q ) ). + +************************************************************************* + + out->write( zcl_demo_abap_aux=>heading( `21) CALL TRANSFORMATION Syntax: Results of Transformations` ) ). + "As in the examples above, the predefined identity transformation is used here. + + "Creating demo XML data to be used in the example as the source. + DATA(demo_xml) = cl_abap_conv_codepage=>create_out( )->convert( `Hi ABAP` ). + + out->write( `********** Result options for transforming to XML data ********** ` ). + out->write( |\n| ). + + "Result: Data object of type string + "The example uses the OPTIONS addition. The XML header should not be added. + DATA str_g TYPE string. + CALL TRANSFORMATION id SOURCE XML demo_xml + RESULT XML str_g + OPTIONS xml_header = 'NO'. + + out->write( `Result: Data object of type string` ). + out->write( str_g ). + out->write( |\n| ). + + "Data object of type xstring + DATA xml_r TYPE xstring. + CALL TRANSFORMATION id SOURCE XML demo_xml + RESULT XML xml_r. + + DATA(conv_xml_r) = cl_abap_conv_codepage=>create_in( )->convert( xml_r ). + out->write( `Result: Data object of type xstring` ). + out->write( format( conv_xml_r ) ). + out->write( |\n| ). + + "Data object declared inline (e.g. DATA(a) or FINAL(b)), which has then the type xstring + CALL TRANSFORMATION id SOURCE XML demo_xml + RESULT XML DATA(xml_s). + + DATA(conv_xml_s) = cl_abap_conv_codepage=>create_in( )->convert( xml_s ). + out->write( `Result: Data object declared inline (type xstring)` ). + out->write( format( conv_xml_s ) ). + out->write( |\n| ). + + "Standard table with character-like line type + DATA stdtab_clike_b TYPE c50_tab_type. + CALL TRANSFORMATION id SOURCE XML demo_xml + RESULT XML stdtab_clike_b + OPTIONS xml_header = 'NO'. + + out->write( `Result: Standard table with character-like line type` ). + out->write( stdtab_clike_b ). + out->write( |\n| ). + + "Standard table with byte-like line type + DATA stdtab_bytelike_b TYPE x30_tab_type. + CALL TRANSFORMATION id SOURCE XML demo_xml + RESULT XML stdtab_bytelike_b. + + out->write( `Result: Standard table with byte-like line type` ). + out->write( stdtab_bytelike_b ). + out->write( |\n| ). + + "Furthermore, some references to iXML and sXML libraries are possible. + "The following example covers sXML (an object reference variable of type ref to cl_sxml_string_writer) + "Other types are possible, for example JSON writers. + DATA(writer4tr) = cl_sxml_string_writer=>create( type = if_sxml=>co_xt_xml10 ). + CALL TRANSFORMATION id SOURCE XML demo_xml + RESULT XML writer4tr. + + DATA(xml_t) = writer4tr->get_output( ). + DATA(conv_xml_t) = cl_abap_conv_codepage=>create_in( )->convert( xml_t ). + out->write( `Result: Object reference variable with type ref to cl_sxml_string_writer` ). + out->write( format( conv_xml_t ) ). + out->write( |\n| ). + + out->write( `********** Result options for transforming to ABAP data **********` ). + out->write( |\n| ). + + "Similar to above, multiple ABAP data objects can be specified as a static parameter list. + "Here, the example from above is used. The tranformation is performed the other way round. + DATA d_i LIKE a_i. + DATA e_str LIKE b_str. + DATA f_p LIKE c_p. + + CALL TRANSFORMATION id SOURCE XML xml_p + RESULT x = d_i + y = e_str + z = f_p. + + out->write( `Result: Multiple ABAP data objects in a static parameter list` ). + out->write( d_i ). + out->write( e_str ). + out->write( f_p ). + out->write( |\n| ). + + "Specifying an internal table of type abap_trans_resbind_tab + DATA g_i LIKE a_i. + DATA h_str LIKE b_str. + DATA i_p LIKE c_p. + + "Note: Only bound parts are deserialized, i.e. the result table must be + "filled accordingly. + DATA(restab) = VALUE abap_trans_resbind_tab( + ( name = 'X' value = REF #( d_i ) ) + ( name = 'Y' value = REF #( e_str ) ) + ( name = 'Z' value = REF #( f_p ) ) ). + + CALL TRANSFORMATION id SOURCE XML xml_q + RESULT (restab). + + out->write( `Result: Multiple ABAP data objects in an internal table` ). + out->write( restab ). + +************************************************************************ + + out->write( zcl_demo_abap_aux=>heading( `22) Dealing with JSON Data` ) ). + "Note: When the identity transformation ID is used, the format is asJSON. + + "Elementary type + DATA str_h TYPE string VALUE `Hello`. + "ABAP -> JSON + "Creating a JSON writer + DATA(json_wr_a) = cl_sxml_string_writer=>create( type = if_sxml=>co_xt_json ). + + CALL TRANSFORMATION id SOURCE hi = str_h + RESULT XML json_wr_a. + + DATA(json_a) = cl_abap_conv_codepage=>create_in( )->convert( json_wr_a->get_output( ) ). + + out->write( `ABAP -> JSON: Elementary type` ). + out->write( json_a ). + out->write( |\n| ). + + "JSON -> ABAP + DATA str_i TYPE string. + "Note: CALL TRANSFORMATION handles JSON sources implicitly. + CALL TRANSFORMATION id SOURCE XML json_a + RESULT hi = str_i. + + out->write( `JSON -> ABAP: Elementary type` ). + out->write( str_i ). + out->write( |\n| ). + + "Structure + SELECT SINGLE carrid, carrname, currcode, url + FROM zdemo_abap_carr + WHERE carrid = 'AZ' + INTO @DATA(carr_struc_c). + + "ABAP -> JSON + DATA(json_wr_b) = cl_sxml_string_writer=>create( type = if_sxml=>co_xt_json ). + + CALL TRANSFORMATION id SOURCE structure = carr_struc_c + RESULT XML json_wr_b. + + DATA(json_b) = cl_abap_conv_codepage=>create_in( )->convert( json_wr_b->get_output( ) ). + out->write( `ABAP -> JSON: Structure` ). + out->write( json_b ). + out->write( |\n| ). + + "JSON -> ABAP + DATA carr_struc_d LIKE carr_struc_c. + CALL TRANSFORMATION id SOURCE XML json_b + RESULT structure = carr_struc_d. + + out->write( `JSON -> ABAP: Structure` ). + out->write( carr_struc_d ). + out->write( |\n| ). + + "Internal table + SELECT carrid, carrname, currcode, url + FROM zdemo_abap_carr + INTO TABLE @DATA(carr_tab_c) + UP TO 2 ROWS. + + "ABAP -> JSON + "This examples uses a cast to get access to further methods. + DATA(json_wr_c) = cl_sxml_string_writer=>create( type = if_sxml=>co_xt_json ). + DATA(json_wr_cast) = CAST if_sxml_writer( json_wr_c ). + + "With the following method calls, the result is formatted. + json_wr_cast->set_option( option = if_sxml_writer=>co_opt_linebreaks ). + json_wr_cast->set_option( option = if_sxml_writer=>co_opt_indent ). + + CALL TRANSFORMATION id SOURCE itab = carr_tab_c + RESULT XML json_wr_c. + + DATA(json_c) = cl_abap_conv_codepage=>create_in( )->convert( json_wr_c->get_output( ) ). + out->write( `ABAP -> JSON: Internal table` ). + out->write( json_c ). + out->write( |\n| ). + + "JSON -> ABAP + DATA carr_tab_d LIKE carr_tab_c. + + CALL TRANSFORMATION id SOURCE XML json_c + RESULT itab = carr_tab_d. + + out->write( `JSON -> ABAP: Internal table` ). + out->write( carr_tab_d ). + out->write( |\n| ). + + "JSON -> XML + DATA(str_j) = + `{` && + `"flights": [` && + ` {` && + ` "carrier": "LH",` && + ` "connectionid": "400",` && + ` "from": "Frankfurt",` && + ` "to": "Berlin"` && + ` },` && + ` {` && + ` "carrier": "DL",` && + ` "connectionid": "400",` && + ` "from": "San Francisco",` && + ` "to": "New York"` && + ` }` && + `]` && + `}`. + + DATA(json_d) = cl_abap_conv_codepage=>create_out( )->convert( str_j ). + DATA(json_wr_d) = cl_sxml_string_reader=>create( json_d ). + DATA json2xml_ct TYPE xstring. + + "JSON -> XML using CALL TRANSFORMATION + CALL TRANSFORMATION id SOURCE XML json_wr_d + RESULT XML json2xml_ct. + + DATA(conv_json2xml_ct) = cl_abap_conv_codepage=>create_in( )->convert( json2xml_ct ). + + out->write( `JSON -> XML using CALL TRANSFORMATION` ). + out->write( format( conv_json2xml_ct ) ). + out->write( |\n| ). + + "JSON -> XML using sXML + DATA(reader_a) = cl_sxml_string_reader=>create( cl_abap_conv_codepage=>create_out( + )->convert( str_j ) ). + "XML writer (note the type specification in contrast to the previous examples) + DATA(xml_wr) = cl_sxml_string_writer=>create( type = if_sxml=>co_xt_xml10 ). + + TRY. + reader_a->next_node( ). + "The reader parses the data in one go by calling the SKIP_NODE method. + "The data is passed to an XML writer. + reader_a->skip_node( xml_wr ). + CATCH cx_sxml_parse_error INTO DATA(err_pa). + out->write( err_pa->get_text( ) ). + ENDTRY. + + DATA(json2xml_sxml) = cl_abap_conv_codepage=>create_in( )->convert( xml_wr->get_output( ) ). + out->write( `JSON -> XML using sXML` ). + out->write( format( json2xml_sxml ) ). + out->write( |\n| ). + + "XML -> JSON using CALL TRANSFORMATION + DATA(json_wr_f) = cl_sxml_string_writer=>create( type = if_sxml=>co_xt_json ). + + CALL TRANSFORMATION id SOURCE XML json2xml_sxml + RESULT XML json_wr_f. + + DATA(xml2json_ct) = cl_abap_conv_codepage=>create_in( )->convert( json_wr_f->get_output( ) ). + out->write( `XML -> JSON using CALL TRANSFORMATION` ). + out->write( xml2json_ct ). + out->write( |\n| ). + + "XML -> JSON using sXML + DATA(reader_b) = cl_sxml_string_reader=>create( cl_abap_conv_codepage=>create_out( )->convert( xml2json_ct ) ). + DATA(json_wr) = cl_sxml_string_writer=>create( type = if_sxml=>co_xt_json ). + + TRY. + reader_b->next_node( ). + reader_b->skip_node( json_wr ). + CATCH cx_sxml_parse_error INTO DATA(err_xj). + out->write( err_xj->get_text( ) ). + ENDTRY. + + DATA(xml2json_sxml) = cl_abap_conv_codepage=>create_in( )->convert( json_wr->get_output( ) ). + out->write( `XML -> JSON using sXML` ). + out->write( xml2json_sxml ). + +************************************************************************ + + out->write( zcl_demo_abap_aux=>heading( `23) XCO Classes for JSON` ) ). + "Note: Unlike above, the following snippets do not work with asJSON as intermediate + "format. + + DATA: BEGIN OF carrier_struc, + carrier_id TYPE c length 3, + connection_id TYPE n length 4, + city_from TYPE c length 20, + city_to TYPE c length 20, + END OF carrier_struc. + + DATA carriers_tab like TABLE OF carrier_struc WITH EMPTY KEY. + + carrier_struc = VALUE #( carrier_id = 'AA' connection_id = '17' city_from = 'New York' city_to = 'San Francisco' ). + carriers_tab = VALUE #( ( carrier_id = 'AZ' connection_id = '788' city_from = 'Rome' city_to = 'Tokyo' ) + ( carrier_id = 'JL' connection_id = '408' city_from = 'Frankfurt' city_to = 'Tokyo' ) + ( carrier_id = 'LH' connection_id = '2402' city_from = 'Frankfurt' city_to = 'Berlin' ) ). + + "ABAP (structure) -> JSON using XCO + DATA(struc2json_xco) = xco_cp_json=>data->from_abap( carrier_struc )->to_string( ). + out->write( `ABAP (structure) -> JSON using XCO` ). + out->write( format( input = struc2json_xco xml = abap_false ) ). + out->write( |\n| ). + + "ABAP (internal table) -> JSON using XCO + DATA(itab2json_xco) = xco_cp_json=>data->from_abap( carriers_tab )->to_string( ). + out->write( `ABAP (internal table) -> JSON using XCO` ). + out->write( format( input = itab2json_xco xml = abap_false ) ). + out->write( |\n| ). + + "JSON -> ABAP (structure) using XCO + DATA json2struc_xco LIKE carrier_struc. + xco_cp_json=>data->from_string( struc2json_xco )->write_to( REF #( json2struc_xco ) ). + out->write( `JSON -> ABAP (structure) using XCO` ). + out->write( json2struc_xco ). + out->write( |\n| ). + + "JSON -> ABAP (internal table) using XCO + DATA json2itab_xco LIKE carriers_tab. + xco_cp_json=>data->from_string( itab2json_xco )->write_to( REF #( json2itab_xco ) ). + out->write( `JSON -> ABAP (internal table) using XCO` ). + out->write( json2itab_xco ). + out->write( |\n| ). + + "Creating JSON using XCO + "Check out more methods that offer more options to build the JSON by clicking + "CTRL + Space after '->' in ADT. + DATA(json_builder_xco) = xco_cp_json=>data->builder( ). + json_builder_xco->begin_object( + )->add_member( 'CarrierId' )->add_string( 'DL' + )->add_member( 'ConnectionId' )->add_string( '1984' + )->add_member( 'CityFrom' )->add_string( 'San Francisco' + )->add_member( 'CityTo' )->add_string( 'New York' + )->end_object( ). + + "Getting JSON data + DATA(json_created_xco) = json_builder_xco->get_data( )->to_string( ). + + out->write( `Creating JSON using XCO` ). + out->write( format( input = json_created_xco xml = abap_false ) ). + out->write( |\n| ). + + "Transforming the created JSON to ABAP (structure) + "Note: The JSON was intentionally created without the underscores in the + "name to demonstrate the 'apply' method. The following example demonstrates + "a transformation of camel case and underscore notation. As above, check out + "more options by clicking CTRL + Space after '...transformation->'. + CLEAR json2struc_xco. + xco_cp_json=>data->from_string( json_created_xco )->apply( VALUE #( + ( xco_cp_json=>transformation->pascal_case_to_underscore ) ) )->write_to( REF #( json2struc_xco ) ). + + out->write( `JSON -> ABAP (structure) using XCO demonstrating the apply method` ). + out->write( json2struc_xco ). + +************************************************************************ + + out->write( zcl_demo_abap_aux=>heading( `24) Excursion: Compressing and Decompressing Binary Data` ) ). + "You may want to process or store binary data. The data can be very large. + "You can compress the data in gzip format and decompress it for further processing using + "the cl_abap_gzip class. Check out appropriate exceptions to be caught. The simple example + "just specifies cx_root. See the class documentation for more information. + "This example uses a data object of type xstring from a previous example. + + "Compressing binary data + DATA xstr_comp TYPE xstring. + TRY. + cl_abap_gzip=>compress_binary( EXPORTING raw_in = xml_oref_a + IMPORTING gzip_out = xstr_comp ). + CATCH cx_root INTO DATA(error_comp). + out->write( error_comp->get_text( ) ). + ENDTRY. + + "Decompressing binary data + DATA xstr_decomp TYPE xstring. + TRY. + cl_abap_gzip=>decompress_binary( EXPORTING gzip_in = xstr_comp + IMPORTING raw_out = xstr_decomp ). + + CATCH cx_root INTO DATA(error_decomp). + out->write( error_decomp->get_text( ) ). + ENDTRY. + + "Checking the xstring length of the variables used and comparing the result + DATA(strlen_original_xstring) = xstrlen( xml_oref_a ). + out->write( |Length of original binary data object: { strlen_original_xstring }| ). + DATA(strlen_comp) = xstrlen( xstr_comp ). + out->write( |Length of compressed binary data object: { strlen_comp }| ). + DATA(strlen_decomp) = xstrlen( xstr_decomp ). + out->write( |Length of decompressed binary data object: { strlen_decomp }| ). + IF xml_oref_a = xstr_decomp. + out->write( `The decompressed binary data object has the same value as the original binary data object.` ). + ENDIF. + ENDMETHOD. + METHOD format. + TRY. + DATA(xstr) = cl_abap_conv_codepage=>create_out( )->convert( input ). + DATA(reader) = cl_sxml_string_reader=>create( xstr ). + DATA(writer) = CAST if_sxml_writer( cl_sxml_string_writer=>create( + type = COND #( WHEN xml = abap_true THEN if_sxml=>co_xt_xml10 ELSE if_sxml=>co_xt_json ) ) ). + writer->set_option( option = if_sxml_writer=>co_opt_linebreaks ). + writer->set_option( option = if_sxml_writer=>co_opt_indent ). + reader->next_node( ). + reader->skip_node( writer ). + string = cl_abap_conv_codepage=>create_in( )->convert( CAST cl_sxml_string_writer( writer )->get_output( ) ). + CATCH cx_root. + string = `Issue when formatting.`. + ENDTRY. + + ENDMETHOD. + + METHOD class_constructor. + "Filling demo database tables. + zcl_demo_abap_aux=>fill_dbtabs( ). + ENDMETHOD. + + METHOD concatenate_string. + attr_concat_string = attr_string_a && attr_string_b. + ENDMETHOD. + + METHOD deserialize_helper. + me->attr_string_a = attr_string_a. + me->attr_string_b = attr_string_b. + me->attr_concat_string = attr_concat_string. + ENDMETHOD. + + METHOD serialize_helper. + attr_string_a = me->attr_string_a. + attr_string_b = me->attr_string_b. + attr_concat_string = me->attr_concat_string. + ENDMETHOD. + + METHOD lowercase_string. + attr_lowercase_str = to_lower( attr_string_a && attr_string_b ). + ENDMETHOD. + ENDCLASS. \ No newline at end of file