Update
This commit is contained in:
@@ -15,6 +15,7 @@
|
||||
- [Creating Anonymous Structures](#creating-anonymous-structures)
|
||||
- [Variants of Structures](#variants-of-structures)
|
||||
- [Accessing (Components of) Structures](#accessing-components-of-structures)
|
||||
- [ASSIGN Statements](#assign-statements)
|
||||
- [Populating Structures](#populating-structures)
|
||||
- [Using the VALUE Operator](#using-the-value-operator)
|
||||
- [Using the NEW Operator](#using-the-new-operator)
|
||||
@@ -462,6 +463,102 @@ Nested components can be addressed using chaining:
|
||||
|
||||
<p align="right"><a href="#top">⬆️ back to top</a></p>
|
||||
|
||||
### ASSIGN Statements
|
||||
|
||||
```abap
|
||||
"A field symbol is set using an assignment of a memory area to the
|
||||
"field symbol by ASSIGN statements.
|
||||
"Particularly, field symbols and ASSIGN statements are supporting elements for
|
||||
"dynamic programming. ASSIGN statements have multiple additions. Find more information
|
||||
"and examples in the Dynamic Programming cheat sheet.
|
||||
|
||||
TYPES: BEGIN OF s,
|
||||
comp1 TYPE i,
|
||||
comp2 TYPE c LENGTH 3,
|
||||
comp3 TYPE n LENGTH 5,
|
||||
comp4 TYPE string,
|
||||
END OF s.
|
||||
|
||||
DATA(demo_struc) = VALUE s( comp1 = 1 comp2 = 'abc' comp3 = '12345' comp4 = `ABAP` ).
|
||||
|
||||
"Defining a field symbol
|
||||
FIELD-SYMBOLS <a> TYPE s.
|
||||
|
||||
"Assigning the entire structure to a field symbole
|
||||
ASSIGN demo_struc TO <a>.
|
||||
|
||||
"Accessing a structure component via the field symbol
|
||||
DATA(comp1) = <a>-comp1.
|
||||
|
||||
"Field symbol declared inline
|
||||
"Note: The typing depends on the memory area specified. In this case,
|
||||
"the field symbol <fd> has the structured type s. This is valid for static
|
||||
"assignments. In case of dynamic assignments, the type is the generic type
|
||||
"data.
|
||||
ASSIGN demo_struc TO FIELD-SYMBOL(<b>).
|
||||
comp1 = <b>-comp1.
|
||||
|
||||
"Accessing components of structures by assigning components to field symbols
|
||||
"The field symbols is typed with the generic type data so that all components,
|
||||
"which have random types, can be assigned.
|
||||
FIELD-SYMBOLS <d> TYPE data.
|
||||
ASSIGN demo_struc-comp1 TO <d>.
|
||||
ASSIGN demo_struc-comp2 TO <d>.
|
||||
ASSIGN demo_struc-comp3 TO <d>.
|
||||
ASSIGN demo_struc-comp4 TO <d>.
|
||||
|
||||
"Accessing structures and components dynamically
|
||||
"Note: In case of dynamic assignments, ...
|
||||
"- sy-subrc is set.
|
||||
"- the type of field symbols declared inline is the generic type data.
|
||||
ASSIGN ('DEMO_STRUC') TO FIELD-SYMBOL(<c>).
|
||||
ASSERT sy-subrc = 0.
|
||||
|
||||
"Using ASSIGN COMPONENT statements
|
||||
"It is recommended to use the newer syntax, which sepcifies the component
|
||||
"selector followed by a data object in a pair of parentheses.
|
||||
"After COMPONENT (and in the parentheses in the newer syntax), a character-like
|
||||
"or numeric data object is expected.
|
||||
DATA(some_comp) = `COMP2`.
|
||||
ASSIGN COMPONENT some_comp OF STRUCTURE demo_struc TO <d>.
|
||||
ASSERT sy-subrc = 0.
|
||||
|
||||
some_comp = `COMP5`.
|
||||
ASSIGN COMPONENT some_comp OF STRUCTURE demo_struc TO <d>.
|
||||
ASSERT sy-subrc = 4.
|
||||
|
||||
"Numeric data objects
|
||||
"The data object is implicitly converted to type i (if required) and
|
||||
"interpreted as the position of the component in the structure.
|
||||
ASSIGN COMPONENT 1 OF STRUCTURE demo_struc TO <d>.
|
||||
ASSERT sy-subrc = 0.
|
||||
|
||||
ASSIGN COMPONENT 5 OF STRUCTURE demo_struc TO <d>.
|
||||
ASSERT sy-subrc = 4.
|
||||
|
||||
"0 means that the entire structure is assigned
|
||||
ASSIGN COMPONENT 0 OF STRUCTURE demo_struc TO <d>.
|
||||
ASSERT sy-subrc = 0.
|
||||
ASSERT <d> = demo_struc.
|
||||
|
||||
"Newer syntax using the component selector followed by content in
|
||||
"a pair of parentheses.
|
||||
ASSIGN demo_struc-('COMP4') TO <d>.
|
||||
ASSIGN demo_struc-(some_comp) TO <d>.
|
||||
ASSIGN demo_struc-(3) TO <d>.
|
||||
ASSIGN demo_struc-(0) TO <d>.
|
||||
|
||||
"Iterating across all structure components
|
||||
DO.
|
||||
ASSIGN demo_struc-(sy-index) TO <d>.
|
||||
IF sy-subrc <> 0.
|
||||
EXIT.
|
||||
ENDIF.
|
||||
ENDDO.
|
||||
```
|
||||
|
||||
<p align="right"><a href="#top">⬆️ back to top</a></p>
|
||||
|
||||
## Populating Structures
|
||||
|
||||
You can copy the content of a structure to another using the [assignment operator](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenassignment_operator_glosry.htm) `=`.
|
||||
@@ -1090,7 +1187,7 @@ ENDLOOP.
|
||||
- More information about the purpose of the individual components is available at [ABAP System Fields (F1 documentation for Standard ABAP)](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abensystem_fields.htm).
|
||||
|
||||
|
||||
The following example demonstrates a selection of ABAP system fields. It uses artifacts from the ABAP cheat sheet repository. Note the comments in the code because a syntax warning will be displayed when inserting the code in a demo class that uses ABAP for Cloud Development. It is meant to emphasize that multiple system fields should not to be used in ABAP for Cloud Development.
|
||||
The following example demonstrates a selection of ABAP system fields. It uses artifacts from the ABAP cheat sheet repository. Note the comments in the code because a syntax warning will be displayed when inserting the code in a demo class that uses ABAP for Cloud Development. It is meant to emphasize that multiple system fields should not be used in ABAP for Cloud Development.
|
||||
To try the example out, create a demo class named `zcl_demo_abap` and paste the code into it. After activation, choose *F9* in ADT to execute the class. The example is set up to display output in the console.
|
||||
|
||||
```abap
|
||||
|
||||
@@ -4371,7 +4371,7 @@ Global class
|
||||
<td>
|
||||
|
||||
``` abap
|
||||
CLASS zcl_some_class DEFINITION
|
||||
CLASS zcl_demo_abap DEFINITION
|
||||
PUBLIC
|
||||
FINAL
|
||||
CREATE PUBLIC .
|
||||
@@ -4383,7 +4383,7 @@ CLASS zcl_some_class DEFINITION
|
||||
PRIVATE SECTION.
|
||||
ENDCLASS.
|
||||
|
||||
CLASS zcl_some_class IMPLEMENTATION.
|
||||
CLASS zcl_demo_abap IMPLEMENTATION.
|
||||
METHOD if_oo_adt_classrun~main.
|
||||
|
||||
"Object reference variables
|
||||
@@ -4629,7 +4629,7 @@ Global class
|
||||
<td>
|
||||
|
||||
``` abap
|
||||
CLASS zcl_some_class DEFINITION
|
||||
CLASS zcl_demo_abap DEFINITION
|
||||
PUBLIC
|
||||
FINAL
|
||||
CREATE PUBLIC .
|
||||
@@ -4641,7 +4641,7 @@ CLASS zcl_some_class DEFINITION
|
||||
PRIVATE SECTION.
|
||||
ENDCLASS.
|
||||
|
||||
CLASS zcl_some_class IMPLEMENTATION.
|
||||
CLASS zcl_demo_abap IMPLEMENTATION.
|
||||
METHOD if_oo_adt_classrun~main.
|
||||
|
||||
"Object reference variables
|
||||
|
||||
@@ -319,6 +319,7 @@ FIELD-SYMBOLS:
|
||||
<simple> TYPE simple, "Elementary data type including enumerated types and
|
||||
"structured types with exclusively character-like flat components
|
||||
<object> TYPE REF TO object. "object can only be specified after REF TO; can point to any object
|
||||
"The types REF TO object and REF TO data are considered complete types.
|
||||
|
||||
"Data objects to work with
|
||||
DATA: BEGIN OF s,
|
||||
@@ -428,6 +429,7 @@ ASSIGN s-structure TO <simple>.
|
||||
ASSIGN s-xl1 TO <simple>.
|
||||
"ASSIGN s-tab_ha TO <simple>.
|
||||
|
||||
s-oref = NEW cl_system_uuid( ).
|
||||
ASSIGN s-oref TO <object>.
|
||||
```
|
||||
|
||||
@@ -459,15 +461,20 @@ ASSIGN s-oref TO <object>.
|
||||
#### Declaring Data Reference Variables
|
||||
|
||||
``` abap
|
||||
"Example declarations of data reference variables with static types.
|
||||
"The static types can be complete or generic (but only data can be used).
|
||||
"Note that they do not yet point to a data object. At this stage,
|
||||
"initial reference variables contain null references.
|
||||
"The following example shows a selection of declaration options with data reference
|
||||
"variables with static types. The static types can be complete or generic (but
|
||||
"only data can be used).
|
||||
"Note that the variables do not yet point to a data object. At this stage,
|
||||
"initial reference variables contain null references.
|
||||
DATA num type i.
|
||||
|
||||
DATA: ref_a TYPE REF TO i, "Complete data type
|
||||
ref_b TYPE REF TO some_dbtab, "Complete data type
|
||||
ref_c LIKE REF TO some_data_object,
|
||||
ref_b TYPE REF TO zdemo_abap_carr, "Complete data type
|
||||
ref_c LIKE REF TO num,
|
||||
ref_d TYPE REF TO data, "Generic data type
|
||||
ref_e LIKE ref_a. "Referring to an existing data reference variable
|
||||
ref_e LIKE ref_a, "Referring to an existing data reference variable
|
||||
ref_f TYPE TABLE OF REF TO i, "Reference table, complete data type
|
||||
ref_g TYPE TABLE OF REF TO data. "Reference table, generic data type
|
||||
```
|
||||
|
||||
As shown below, instead of the explicit declaration, inline declarations are also possible.
|
||||
@@ -1047,6 +1054,7 @@ DATA(idx) = line_index( dref->*[ ('CARRID') = 'LH' ] ).
|
||||
Some example contexts of using data references are as follows:
|
||||
|
||||
*Overwriting data reference variables*:
|
||||
|
||||
``` abap
|
||||
DATA dref TYPE REF TO data.
|
||||
dref = NEW i( 1 ).
|
||||
@@ -1108,6 +1116,7 @@ READ TABLE fli_tab INDEX 1 REFERENCE INTO DATA(rt_ref).
|
||||
```
|
||||
|
||||
*Data reference variables as part of structures and internal tables*:
|
||||
|
||||
``` abap
|
||||
"Unlike field symbols, data reference variables can be used as
|
||||
"components of structures or columns in internal tables.
|
||||
@@ -1129,6 +1138,19 @@ APPEND struc TO itab.
|
||||
itab[ 1 ]-ref->* = 123.
|
||||
```
|
||||
|
||||
*Internal tables of type REF TO data can contain any data references*:
|
||||
|
||||
```abap
|
||||
DATA it_ref TYPE TABLE OF REF TO data.
|
||||
|
||||
"Such a table can hold any data type
|
||||
it_ref = VALUE #( ( NEW i( 3 ) ) "Elementary type
|
||||
( NEW string( `hello` ) ) "Elementary type
|
||||
( NEW zdemo_abap_flsch( carrid = 'XY' connid = '1234' ) ) "Structured type
|
||||
( NEW string_table( ( `a` ) ( `b` ) ( `c` ) ) ) "Table type
|
||||
).
|
||||
```
|
||||
|
||||
> **✔️ Hint**<br>
|
||||
> When to actually use either a field symbol
|
||||
or a data reference variable? It depends on your use case. However, data
|
||||
@@ -2309,8 +2331,7 @@ ENDCLASS.
|
||||
|
||||
### Dynamic Method Calls
|
||||
|
||||
|
||||
- The following code snippet shows dynamically specifying method calls.
|
||||
- The following code snippet shows dynamically specifying method calls. Find three example classes below the syntax pattern snippet.
|
||||
- The snippet covers methods. Dynamic method calls require `CALL METHOD` statements.
|
||||
- Find an example of a dynamic function module call - as another example of [procedure](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenprocedure_glosry.htm "Glossary Entry") calls - in the [Program Flow Logic](./13_Program_Flow_Logic.md#function-module-example) cheat sheet.
|
||||
|
||||
@@ -2359,7 +2380,14 @@ CALL METHOD class=>(meth) PARAMETER-TABLE ptab.
|
||||
"The addition EXCEPTION-TABLE for exceptions is not dealt with here.
|
||||
```
|
||||
|
||||
**Example class 1**
|
||||
|
||||
**Click to expand the expandable sections for example code**
|
||||
|
||||
<details>
|
||||
<summary>🟢 Example class 1</summary>
|
||||
<!-- -->
|
||||
|
||||
<br>
|
||||
|
||||
The following example class explores dynamic method calls with simple methods. You can create a demo class called `zcl_demo_abap` and copy and paste the following code. Once activated, you can choose *F9* in ADT to run the class. The example is not designed to display output in the console.
|
||||
|
||||
@@ -2547,8 +2575,16 @@ CLASS zcl_demo_abap IMPLEMENTATION.
|
||||
ENDCLASS.
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<br>
|
||||
|
||||
<details>
|
||||
<summary>🟢 Example class 2</summary>
|
||||
<!-- -->
|
||||
|
||||
<br>
|
||||
|
||||
**Example class 2**
|
||||
|
||||
The following simplified example highlights several things in the context of a dynamic method call example:
|
||||
- Dynamic method call and assigning actual parameters to formal parameters statically
|
||||
@@ -2624,6 +2660,110 @@ CLASS zcl_demo_test IMPLEMENTATION.
|
||||
ENDCLASS.
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<br>
|
||||
|
||||
<details>
|
||||
<summary>🟢 Example class 3</summary>
|
||||
<!-- -->
|
||||
|
||||
<br>
|
||||
|
||||
The following example demonstrates dynamic method calls with methods defined in interfaces.
|
||||
|
||||
<table>
|
||||
|
||||
<tr>
|
||||
<td> Class include </td> <td> Code </td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
Global class
|
||||
|
||||
</td>
|
||||
|
||||
<td>
|
||||
|
||||
``` abap
|
||||
CLASS zcl_demo_abap DEFINITION
|
||||
PUBLIC
|
||||
FINAL
|
||||
CREATE PUBLIC .
|
||||
|
||||
PUBLIC SECTION.
|
||||
INTERFACES if_oo_adt_classrun.
|
||||
PROTECTED SECTION.
|
||||
PRIVATE SECTION.
|
||||
ENDCLASS.
|
||||
|
||||
CLASS zcl_demo_abap IMPLEMENTATION.
|
||||
METHOD if_oo_adt_classrun~main.
|
||||
|
||||
"Creating an instance of the local class that implements
|
||||
"an interface
|
||||
DATA(oref) = NEW lcl( ).
|
||||
|
||||
"Static method call
|
||||
DATA(number) = oref->lif~get_number( ).
|
||||
out->write( number ).
|
||||
|
||||
"Dynamic method call
|
||||
"Note the uppercase.
|
||||
TRY.
|
||||
CALL METHOD oref->('lif~get_number') RECEIVING number = number.
|
||||
out->write( number ).
|
||||
CATCH cx_sy_dyn_call_illegal_method INTO DATA(error).
|
||||
DATA(error_text) = error->get_text( ).
|
||||
out->write( error_text ).
|
||||
ENDTRY.
|
||||
|
||||
CALL METHOD oref->('LIF~GET_NUMBER') RECEIVING number = number.
|
||||
out->write( number ).
|
||||
ENDMETHOD.
|
||||
ENDCLASS.
|
||||
```
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
CCIMP include (*Local Types* tab in ADT)
|
||||
|
||||
</td>
|
||||
|
||||
<td>
|
||||
|
||||
``` abap
|
||||
INTERFACE lif.
|
||||
METHODS get_number RETURNING VALUE(number) TYPE i.
|
||||
ENDINTERFACE.
|
||||
|
||||
CLASS lcl DEFINITION.
|
||||
PUBLIC SECTION.
|
||||
INTERFACES lif.
|
||||
ENDCLASS.
|
||||
|
||||
CLASS lcl IMPLEMENTATION.
|
||||
METHOD lif~get_number.
|
||||
number = cl_abap_random_int=>create( seed = cl_abap_random=>seed( )
|
||||
min = 1
|
||||
max = 1000 )->get_next( ).
|
||||
ENDMETHOD.
|
||||
ENDCLASS.
|
||||
```
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
</details>
|
||||
|
||||
|
||||
<p align="right"><a href="#top">⬆️ back to top</a></p>
|
||||
|
||||
### Dynamic Function Module Calls
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
- [ABAP Behavior Pools (ABP)](#abap-behavior-pools-abp)
|
||||
- [RAP Handler Classes and Methods](#rap-handler-classes-and-methods)
|
||||
- [RAP Saver Class and Saver Methods](#rap-saver-class-and-saver-methods)
|
||||
- [ABP Auxiliary Classes](#abp-auxiliary-classes)
|
||||
- [BDEF Derived Types](#bdef-derived-types)
|
||||
- [BDEF Derived Type Syntax and Declaring Data Types and Data Objects](#bdef-derived-type-syntax-and-declaring-data-types-and-data-objects)
|
||||
- [Components of BDEF Derived Types](#components-of-bdef-derived-types)
|
||||
@@ -577,8 +578,7 @@ sequence](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?f
|
||||
methods](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabp_saver_method_glosry.htm "Glossary Entry")
|
||||
to save data from the transactional buffer to the database).
|
||||
|
||||
> **💡 Note**<br>
|
||||
> You can optionally define auxiliary classes for ABPs using the syntax `... FOR BEHAVIOR OF bdef_name ...`. These classes reference a RAP business object and have enhanced access rights to it. Their main function is to support implementation in an ABAP behavior pool. They achieve this by offering reusable methods and enabling developers to implement RAP behavior simultaneously.
|
||||
|
||||
|
||||
<p align="right"><a href="#top">⬆️ back to top</a></p>
|
||||
|
||||
@@ -751,6 +751,17 @@ ENDCLASS.
|
||||
|
||||
<p align="right"><a href="#top">⬆️ back to top</a></p>
|
||||
|
||||
### ABP Auxiliary Classes
|
||||
|
||||
- You can optionally define auxiliary classes for ABPs using the syntax `... FOR BEHAVIOR OF bdef_name ...`.
|
||||
- These classes are implicitly final global classes and reference a RAP business object.
|
||||
- They have enhanced access rights to RAP BOs, and ABAP EML statements with the `IN LOCAL MODE` and `PRIVILEGED` can be used.
|
||||
- Their main function is to support implementation in an ABAP behavior pool. They achieve this by offering reusable methods and enabling developers to implement RAP behavior simultaneously. Furthermore, they can be used to provide utility methods for raising [RAP business events](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_entity_event_glosry.htm).
|
||||
- Note that RAP handler, saver, and event handler methods as such can only be implemented in a behavior pool, but they can delegate tasks to methods in ABP auxiliary classes. It is not recommended to completely outsource the handler and saver method implementations to auxiliary classes to prevent unnecessary overhead.
|
||||
- As a prerequisite, the ABAP auxiliary class name is specified in the BDEF using the [`auxiliary class ...` notation](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/ABENBDL_AUXILIARY_CLASS.html). Multiple ABAP auxiliary classes can be specified.
|
||||
|
||||
<p align="right"><a href="#top">⬆️ back to top</a></p>
|
||||
|
||||
## BDEF Derived Types
|
||||
|
||||
The operands of EML statements and parameters of handler and saver methods are mainly special messenger tables for passing data and receiving results or messages, i. e. the communication between a [RAP BO consumer](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_bo_consumer_glosry.htm) and the [RAP BO provider](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_bo_provider_glosry.htm) using EML consists (in most cases) of exchanging data stored in internal tables that have special ABAP types - [BDEF derived types](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_derived_type_glosry.htm "Glossary Entry").
|
||||
|
||||
@@ -1527,9 +1527,20 @@ DATA(dobj_enum_b) = b.
|
||||
"in special conversions using CONV. A base type is flat, elementary, and
|
||||
"has a maximum length of 16 bytes.
|
||||
DATA some_dobj TYPE c LENGTH 2 VALUE 'ap'.
|
||||
DATA(dobj_enum_c) = CONV t_enum_struc( some_dobj ).
|
||||
"M
|
||||
DATA(dobj_enum_c) = CONV t_enum_struc( some_dobj ).
|
||||
ASSERT dobj_enum_c = en_struc-m.
|
||||
|
||||
"Getting the base value of an enumerated type
|
||||
"hi
|
||||
DATA(base_value_k) = CONV basetype( en_struc-k ).
|
||||
|
||||
"yz
|
||||
DATA(base_value_i) = CONV basetype( i ).
|
||||
|
||||
"1
|
||||
DATA(base_value_b) = CONV i( b ).
|
||||
|
||||
"Conversion not possible
|
||||
DATA some_string TYPE string VALUE 'ap'.
|
||||
"DATA(dobj_enum_d) = CONV t_enum_struc( some_string ).
|
||||
|
||||
351
21_XML_JSON.md
351
21_XML_JSON.md
@@ -102,11 +102,22 @@ Parsing XML data using iXML:
|
||||
"Creating demo XML data to be used in the example as string. Using the cl_abap_conv_codepage
|
||||
"class, you can convert the string to xstring which is required for the example.
|
||||
DATA(some_xml) = cl_abap_conv_codepage=>create_out( )->convert(
|
||||
`<hi>` &&
|
||||
` <word1>hallo</word1>` &&
|
||||
` <word2>how</word2>` &&
|
||||
` <word3>are</word3>` &&
|
||||
`</hi>` ).
|
||||
`<?xml version="1.0"?>` &&
|
||||
`<node attr_a="123">` &&
|
||||
` <subnode1>` &&
|
||||
` <hallo>hi</hallo>` &&
|
||||
` </subnode1>` &&
|
||||
` <subnode2>` &&
|
||||
` <letter>a</letter>` &&
|
||||
` <date format="mm-dd-yyyy">01-01-2025</date>` &&
|
||||
` </subnode2>` &&
|
||||
` <subnode3>` &&
|
||||
` <text attr_b="1" attr_c="a">abc</text>` &&
|
||||
` <text attr_b="2" attr_c="b">def</text>` &&
|
||||
` <text attr_b="3" attr_c="c">ghi</text>` &&
|
||||
` <text attr_b="4" attr_c="d">jkl</text>` &&
|
||||
` </subnode3>` &&
|
||||
`</node>` ).
|
||||
|
||||
"Creating one factory object of the access class cl_ixml_core using the
|
||||
"create method. It is used to access the iXML library.
|
||||
@@ -127,7 +138,7 @@ DATA(parser_pa) = ixml_pa->create_parser(
|
||||
DATA(parsing_check) = parser_pa->parse( ).
|
||||
IF parsing_check = 0. "Parsing was successful
|
||||
|
||||
"--------------------- Directly reading nodes ----------------------
|
||||
"--------------------- Directly reading nodes ----------------------
|
||||
|
||||
"Accessing the root element of the DOM. It can be used as the initial node
|
||||
"for accessing subnodes.
|
||||
@@ -136,30 +147,56 @@ IF parsing_check = 0. "Parsing was successful
|
||||
"First subnode
|
||||
DATA(child_element) = root_element->get_first_child( ).
|
||||
"Gettng the value of that node
|
||||
DATA(child_element_value) = child_element->get_value( ). "hallo
|
||||
DATA(child_element_value) = child_element->get_value( ).
|
||||
"Next adjacent node/getting the value
|
||||
DATA(next_element_value) = child_element->get_next( )->get_value( ). "how
|
||||
DATA(next_element) = child_element->get_next( ).
|
||||
DATA(next_element_value) = next_element->get_value( ).
|
||||
"Direct access using element names
|
||||
"Result: First element searched for
|
||||
DATA(element_by_name) = document_pa->find_from_name( name = `word3` )->get_value( ). "are
|
||||
|
||||
"--------------------- Reading using iterators ----------------------
|
||||
DATA(element_by_name) = document_pa->find_from_name( name = `letter` )->get_value( ).
|
||||
|
||||
"--------------------- Reading using iterators ----------------------
|
||||
|
||||
"i.e. going over the XML nodes one after another
|
||||
|
||||
"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.
|
||||
"Exiting the loop when there are no more nodes to process.
|
||||
EXIT.
|
||||
ELSE.
|
||||
... "Do something, e.g. modify values
|
||||
ENDIF.
|
||||
ENDDO.
|
||||
|
||||
|
||||
DATA xml_nodes TYPE string_table.
|
||||
|
||||
DATA(node_pa) = iterator_pa->get_next( ).
|
||||
"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.
|
||||
WHILE NOT node_pa IS INITIAL.
|
||||
"DATA(indent) = node_pa->get_height( ) * 2.
|
||||
"Rettrieving the node type
|
||||
DATA(node_type) = node_pa->get_type( ).
|
||||
CASE node_type.
|
||||
WHEN if_ixml_node=>co_node_element.
|
||||
APPEND |Element: "{ node_pa->get_name( ) }"| TO xml_nodes.
|
||||
"Retrieving attributes
|
||||
DATA(attributes_pa) = node_pa->get_attributes( ).
|
||||
IF NOT attributes_pa IS INITIAL.
|
||||
DO attributes_pa->get_length( ) TIMES.
|
||||
DATA(attr) = attributes_pa->get_item( sy-index - 1 ).
|
||||
APPEND |Attribute: "{ attr->get_name( ) } = { attr->get_value( ) }"| TO xml_nodes.
|
||||
ENDDO.
|
||||
ENDIF.
|
||||
WHEN if_ixml_node=>co_node_text OR if_ixml_node=>co_node_cdata_section.
|
||||
APPEND |Text: "{ node_pa->get_value( ) }"| TO xml_nodes.
|
||||
|
||||
"When iterating the XML nodes, you may want to perform certain actions, e.g.
|
||||
"modifying values etc. Check out the many methods that are available.
|
||||
"This example just transform the textual content to uppercase using the set_value method.
|
||||
DATA(val) = to_upper( node_pa->get_value( ) ).
|
||||
node_pa->set_value( val ).
|
||||
WHEN OTHERS.
|
||||
...
|
||||
ENDCASE.
|
||||
"Retrieving the next node
|
||||
node_pa = iterator_pa->get_next( ).
|
||||
ENDWHILE.
|
||||
|
||||
"Creating a renderer. It renders the XML document into an output stream
|
||||
"that is used to pass XML data from the renderer.
|
||||
@@ -167,11 +204,48 @@ IF parsing_check = 0. "Parsing was successful
|
||||
ixml_pa->create_renderer( document = document_pa
|
||||
ostream = ixml_pa->create_stream_factory( )->create_ostream_xstring( string = xml_pa )
|
||||
)->render( ).
|
||||
...
|
||||
|
||||
ELSE.
|
||||
"Parsing was not successful.
|
||||
...
|
||||
ENDIF.
|
||||
|
||||
DATA(conv_string) = cl_abap_conv_codepage=>create_in( )->convert( xml_pa ).
|
||||
|
||||
*--- xml_nodes ---
|
||||
*Element: "node"
|
||||
*Attribute: "attr_a = 123"
|
||||
*Element: "subnode1"
|
||||
*Element: "hallo"
|
||||
*Text: "hi"
|
||||
*Element: "subnode2"
|
||||
*Element: "letter"
|
||||
*Text: "a"
|
||||
*Element: "date"
|
||||
*Attribute: "format = mm-dd-yyyy"
|
||||
*Text: "01-01-2025"
|
||||
*Element: "subnode3"
|
||||
*Element: "text"
|
||||
*Attribute: "attr_b = 1"
|
||||
*Attribute: "attr_c = a"
|
||||
*Text: "abc"
|
||||
*Element: "text"
|
||||
*Attribute: "attr_b = 2"
|
||||
*Attribute: "attr_c = b"
|
||||
*Text: "def"
|
||||
*Element: "text"
|
||||
*Attribute: "attr_b = 3"
|
||||
*Attribute: "attr_c = c"
|
||||
*Text: "ghi"
|
||||
*Element: "text"
|
||||
*Attribute: "attr_b = 4"
|
||||
*Attribute: "attr_c = d"
|
||||
*Text: "jkl"
|
||||
|
||||
*--- conv_string ---
|
||||
*<?xml version="1.0" encoding="utf-8"?><node attr_a="123"><subnode1><hallo>HI</hallo></subnode1><subnode2><letter>A</letter>
|
||||
*<date format="mm-dd-yyyy">01-01-2025</date></subnode2><subnode3><text attr_b="1" attr_c="a">ABC</text>
|
||||
*<text attr_b="2" attr_c="b">DEF</text><text attr_b="3" attr_c="c">GHI</text><text attr_b="4" attr_c="d">JKL</text></subnode3></node>
|
||||
```
|
||||
|
||||
<p align="right"><a href="#top">⬆️ back to top</a></p>
|
||||
@@ -307,60 +381,139 @@ Parsing XML data using sXML:
|
||||
```abap
|
||||
"--------------------- 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(
|
||||
`<?xml version="1.0"?>` &&
|
||||
`<node attr_a="123">` &&
|
||||
` <subnode1>` &&
|
||||
` <hallo>hi</hallo>` &&
|
||||
` </subnode1>` &&
|
||||
` <subnode2>` &&
|
||||
` <letter>a</letter>` &&
|
||||
` <date format="mm-dd-yyyy">01-01-2025</date>` &&
|
||||
` </subnode2>` &&
|
||||
` <subnode3>` &&
|
||||
` <text attr_b="1" attr_c="a">abc</text>` &&
|
||||
` <text attr_b="2" attr_c="b">def</text>` &&
|
||||
` <text attr_b="3" attr_c="c">ghi</text>` &&
|
||||
` <text attr_b="4" attr_c="d">jkl</text>` &&
|
||||
` </subnode3>` &&
|
||||
`</node>` ).
|
||||
CATCH cx_sy_conversion_codepage.
|
||||
ENDTRY.
|
||||
|
||||
"Creating an internal table for demonstration purposes
|
||||
DATA: BEGIN OF node_info,
|
||||
node_type TYPE string,
|
||||
name TYPE string,
|
||||
value TYPE string,
|
||||
END OF node_info,
|
||||
nodes_tab LIKE TABLE OF node_info.
|
||||
|
||||
"Creating reader
|
||||
"Note: See the comments for the writer above. It is similar here. For readers,
|
||||
"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.
|
||||
"The example uses the XML data from above.
|
||||
DATA(reader) = cl_sxml_string_reader=>create( xml_oo ).
|
||||
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 choose CTRL + Space.
|
||||
CLEAR node_info.
|
||||
reader->next_node( ).
|
||||
|
||||
"Exiting the loop when reaching the end of the XML data.
|
||||
"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.
|
||||
DATA(node_type) = reader->node_type. "Node type, see the interface if_sxml_node
|
||||
DATA(prefix) = reader->prefix. "Namespace prefix
|
||||
DATA(name) = reader->name. "Name of the element
|
||||
DATA(value_type) = reader->value_type. "Value type, see the interface if_sxml_value
|
||||
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)
|
||||
"For display purposes, the property information is stored in an internal table.
|
||||
"The example here just uses simple demo JSON data. Not all properties are
|
||||
"retrieved and displayed.
|
||||
|
||||
...
|
||||
"Node type, see the interface if_sxml_node
|
||||
node_info-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` ).
|
||||
"Name of the element
|
||||
node_info-name = reader->name.
|
||||
"Character-like value (if it is textual data)
|
||||
node_info-value = COND #( WHEN reader->node_type = if_sxml_node=>co_nt_value THEN reader->value ).
|
||||
APPEND node_info 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 = `CO_NT_ATTRIBUTE`
|
||||
name = reader->name
|
||||
value = reader->value ) TO nodes_tab.
|
||||
ENDDO.
|
||||
ENDIF.
|
||||
ENDDO.
|
||||
CATCH cx_sxml_parse_error.
|
||||
...
|
||||
CATCH cx_sxml_state_error INTO DATA(error_parse_token).
|
||||
DATA(error_text) = error_parse_token->get_text( ).
|
||||
ENDTRY.
|
||||
|
||||
*--- nodes_tab ---
|
||||
*NODE_TYPE NAME VALUE
|
||||
*CO_NT_ELEMENT_OPEN node
|
||||
*CO_NT_ATTRIBUTE attr_a 123
|
||||
*CO_NT_ELEMENT_OPEN subnode1
|
||||
*CO_NT_ELEMENT_OPEN hallo
|
||||
*CO_NT_VALUE hallo hi
|
||||
*CO_NT_ELEMENT_CLOSE hallo
|
||||
*CO_NT_ELEMENT_CLOSE subnode1
|
||||
*CO_NT_ELEMENT_OPEN subnode2
|
||||
*CO_NT_ELEMENT_OPEN letter
|
||||
*CO_NT_VALUE letter a
|
||||
*CO_NT_ELEMENT_CLOSE letter
|
||||
*CO_NT_ELEMENT_OPEN date
|
||||
*CO_NT_ATTRIBUTE format mm-dd-yyyy
|
||||
*CO_NT_VALUE date 01-01-2025
|
||||
*CO_NT_ELEMENT_CLOSE date
|
||||
*CO_NT_ELEMENT_CLOSE subnode2
|
||||
*CO_NT_ELEMENT_OPEN subnode3
|
||||
*CO_NT_ELEMENT_OPEN text
|
||||
*CO_NT_ATTRIBUTE attr_b 1
|
||||
*CO_NT_ATTRIBUTE attr_c a
|
||||
*CO_NT_VALUE text abc
|
||||
*CO_NT_ELEMENT_CLOSE text
|
||||
*CO_NT_ELEMENT_OPEN text
|
||||
*CO_NT_ATTRIBUTE attr_b 2
|
||||
*CO_NT_ATTRIBUTE attr_c b
|
||||
*CO_NT_VALUE text def
|
||||
*CO_NT_ELEMENT_CLOSE text
|
||||
*CO_NT_ELEMENT_OPEN text
|
||||
*CO_NT_ATTRIBUTE attr_b 3
|
||||
*CO_NT_ATTRIBUTE attr_c c
|
||||
*CO_NT_VALUE text ghi
|
||||
*CO_NT_ELEMENT_CLOSE text
|
||||
*CO_NT_ELEMENT_OPEN text
|
||||
*CO_NT_ATTRIBUTE attr_b 4
|
||||
*CO_NT_ATTRIBUTE attr_c d
|
||||
*CO_NT_VALUE text jkl
|
||||
*CO_NT_ELEMENT_CLOSE text
|
||||
*CO_NT_ELEMENT_CLOSE subnode3
|
||||
*CO_NT_ELEMENT_CLOSE node
|
||||
|
||||
"--------------------- Object-oriented parsing ----------------------
|
||||
|
||||
"Creating demo XML data to be used in the example.
|
||||
DATA(xml_oo_read) = cl_abap_conv_codepage=>create_out( )->convert(
|
||||
`<?xml version="1.0"?>` &&
|
||||
`<node attr_a="123">` &&
|
||||
` <subnode1>` &&
|
||||
` <status>A</status>` &&
|
||||
` <date format="mm-dd-yyyy">01-01-2024</date>` &&
|
||||
` </subnode1>` &&
|
||||
` <subnode2>` &&
|
||||
` <text attr_b="1" attr_c="a">abc</text>` &&
|
||||
` <text attr_b="2" attr_c="b">def</text>` &&
|
||||
` <text attr_b="3" attr_c="c">ghi</text>` &&
|
||||
` </subnode2>` &&
|
||||
`</node>` ).
|
||||
"The example uses the XML from above
|
||||
CLEAR nodes_tab.
|
||||
DATA(reader_oo) = cl_sxml_string_reader=>create( xml_to_parse ).
|
||||
|
||||
"Creating reader
|
||||
DATA(reader_oo) = cl_sxml_string_reader=>create( xml_oo_read ).
|
||||
TRY.
|
||||
DO.
|
||||
"To iterate accros all nodes, you can call the READ_NEXT_NODE method.
|
||||
@@ -377,21 +530,93 @@ TRY.
|
||||
"Getting the node type
|
||||
DATA(n_type) = node_oo->type.
|
||||
|
||||
"When the parser is currently on the node of an element opening,
|
||||
"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.
|
||||
IF n_type = if_sxml_node=>co_nt_element_open.
|
||||
DATA(attributes) = CAST if_sxml_open_element( node_oo )->get_attributes( ).
|
||||
...
|
||||
ENDIF.
|
||||
...
|
||||
|
||||
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`
|
||||
name = open_element->qname-name
|
||||
) TO nodes_tab.
|
||||
|
||||
DATA(attributes) = open_element->get_attributes( ).
|
||||
|
||||
LOOP AT attributes INTO DATA(attribute).
|
||||
APPEND VALUE #( node_type = `attribute`
|
||||
name = attribute->qname-name
|
||||
value = SWITCH #( attribute->value_type WHEN if_sxml_value=>co_vt_text THEN attribute->get_value( ) )
|
||||
) 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`
|
||||
name = close_element->qname-name
|
||||
) 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( ) )
|
||||
) TO nodes_tab.
|
||||
|
||||
WHEN OTHERS.
|
||||
APPEND VALUE #( node_type = `Error` ) TO nodes_tab.
|
||||
ENDCASE.
|
||||
ENDDO.
|
||||
CATCH cx_sxml_parse_error.
|
||||
...
|
||||
CATCH cx_sxml_state_error INTO DATA(error_parse_oo).
|
||||
DATA(error_parse_oo_text) = error_parse_oo->get_text( ).
|
||||
ENDTRY.
|
||||
|
||||
*--- nodes_tab ---
|
||||
*NODE_TYPE NAME VALUE
|
||||
*open element node
|
||||
*attribute attr_a 123
|
||||
*open element subnode1
|
||||
*open element hallo
|
||||
*value hi
|
||||
*close element hallo
|
||||
*close element subnode1
|
||||
*open element subnode2
|
||||
*open element letter
|
||||
*value a
|
||||
*close element letter
|
||||
*open element date
|
||||
*attribute format mm-dd-yyyy
|
||||
*value 01-01-2025
|
||||
*close element date
|
||||
*close element subnode2
|
||||
*open element subnode3
|
||||
*open element text
|
||||
*attribute attr_b 1
|
||||
*attribute attr_c a
|
||||
*value abc
|
||||
*close element text
|
||||
*open element text
|
||||
*attribute attr_b 2
|
||||
*attribute attr_c b
|
||||
*value def
|
||||
*close element text
|
||||
*open element text
|
||||
*attribute attr_b 3
|
||||
*attribute attr_c c
|
||||
*value ghi
|
||||
*close element text
|
||||
*open element text
|
||||
*attribute attr_b 4
|
||||
*attribute attr_c d
|
||||
*value jkl
|
||||
*close element text
|
||||
*close element subnode3
|
||||
*close element node
|
||||
```
|
||||
|
||||
<p align="right"><a href="#top">⬆️ back to top</a></p>
|
||||
@@ -1479,7 +1704,7 @@ ENDCLASS.
|
||||
### Converting string <-> xstring
|
||||
In the code snippets above and in the executable example, many operations are performed using binary data.
|
||||
This excursion shows the conversion of string <-> xstring using a codepage. The examples use UTF-8.
|
||||
For example, you can use the `cl_abap_conv_codepage` class and the [XCO library](https://help.sap.com/docs/btp/sap-business-technology-platform/xco-library?version=Cloud). Using the `xco_cp` class of the XCO library, you can also process Base64 representations of raw binary data (see the snippet for `xco_cp` in the [String Processing](/22_Released_ABAP_Classes.md#string-processing) section of the *Regular ABAP Classes* cheat sheet).
|
||||
For example, you can use the `cl_abap_conv_codepage` class and the [XCO library](https://help.sap.com/docs/btp/sap-business-technology-platform/xco-library?version=Cloud). Using the `xco_cp` class of the XCO library, you can also process Base64 representations of raw binary data (see the snippet for `xco_cp` in the [String Processing](/22_Released_ABAP_Classes.md#string-processing) section of the *Released ABAP Classes* cheat sheet).
|
||||
|
||||
```abap
|
||||
DATA(xml_string) = `<TXT>ABAP</TXT>`.
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
|
||||
- [Released ABAP Classes](#released-abap-classes)
|
||||
- [Excursion: Available Classes in ABAP for Cloud Development](#excursion-available-classes-in-abap-for-cloud-development)
|
||||
- [Creating and Transforming UUIDs](#creating-and-transforming-uuids)
|
||||
- [Displaying Output in the ADT Console](#displaying-output-in-the-adt-console)
|
||||
- [Creating and Transforming UUIDs](#creating-and-transforming-uuids)
|
||||
- [RAP](#rap)
|
||||
- [Transactional Consistency](#transactional-consistency)
|
||||
- [Numbers and Calculations](#numbers-and-calculations)
|
||||
@@ -68,65 +68,80 @@ SELECT ReleasedObjectType, ReleasedObjectName, ReleaseState
|
||||
INTO TABLE @DATA(released_classes).
|
||||
```
|
||||
|
||||
## Creating and Transforming UUIDs
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td> Class </td> <td> Details/Code Snippet </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> <code>CL_SYSTEM_UUID</code> </td>
|
||||
<td>
|
||||
Creating and and converting system UUIDs with various algorithms
|
||||
<br><br>
|
||||
|
||||
``` abap
|
||||
"Creating UUIDs in binary format (16 bytes)
|
||||
TRY.
|
||||
DATA(uuid) = cl_system_uuid=>create_uuid_x16_static( ) .
|
||||
CATCH cx_uuid_error.
|
||||
ENDTRY.
|
||||
|
||||
"e.g. B2B012691AC31EDEADA0A495A7130961
|
||||
```
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> <code>XCO_CP_UUID</code> </td>
|
||||
<td>
|
||||
Transforming between different UUID formats
|
||||
<br><br>
|
||||
|
||||
``` abap
|
||||
DATA(uuid_c36) = xco_cp_uuid=>format->c36->to_uuid( '7cd44fff-036a-4155-b0d2-f5a4dfbcee92' ).
|
||||
|
||||
"7CD44FFF036A4155B0D2F5A4DFBCEE92
|
||||
DATA(uuid_c36_to_c32) = CONV sysuuid_c32( xco_cp_uuid=>format->c32->from_uuid( uuid_c36 ) ).
|
||||
|
||||
"7cd44fff-036a-4155-b0d2-f5a4dfbcee92
|
||||
DATA(uuid_c32_to_c36) = to_lower( CONV sysuuid_c36( xco_cp_uuid=>format->c36->from_uuid( uuid_c36 ) ) ).
|
||||
```
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p align="right"><a href="#top">⬆️ back to top</a></p>
|
||||
|
||||
## Displaying Output in the ADT Console
|
||||
|
||||
The table includes the <code>IF_OO_ADT_CLASSRUN</code> interface.
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td> Class </td> <td> Details/Code Snippet </td>
|
||||
<td> Interface/Class </td> <td> Details/Code Snippet </td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> <code>IF_OO_ADT_CLASSRUN</code> </td>
|
||||
<td>
|
||||
|
||||
- By implementing the <code>IF_OO_ADT_CLASSRUN</code> interface in a global class, you can make the class executable.
|
||||
- In ADT, you can execute the class using F9.
|
||||
- The statements that are processed when executing the class can be included in the implementation of the `if_oo_adt_classrun~main` method.
|
||||
- Using `out->write( ... ).` statements, you can output the content of data objects to the ADT console. The `name` parameter can be used to precede the data object content with a string.
|
||||
|
||||
<br>
|
||||
|
||||
``` abap
|
||||
CLASS zcl_demo_abap DEFINITION
|
||||
PUBLIC
|
||||
FINAL
|
||||
CREATE PUBLIC .
|
||||
|
||||
PUBLIC SECTION.
|
||||
INTERFACES if_oo_adt_classrun.
|
||||
PROTECTED SECTION.
|
||||
PRIVATE SECTION.
|
||||
ENDCLASS.
|
||||
|
||||
CLASS zcl_demo_abap IMPLEMENTATION.
|
||||
METHOD if_oo_adt_classrun~main.
|
||||
out->write( `Hello world` ).
|
||||
|
||||
TYPES: BEGIN OF s,
|
||||
comp1 TYPE string,
|
||||
comp2 TYPE i,
|
||||
comp3 TYPE string_table,
|
||||
comp4 TYPE REF TO string,
|
||||
END OF s,
|
||||
it_type TYPE TABLE OF s WITH EMPTY KEY.
|
||||
|
||||
DATA(struct) = VALUE s( comp1 = `Hello`
|
||||
comp2 = 1
|
||||
comp3 = VALUE #( ( `a` ) ( `b` ) ( `a` ) ( `p` ) )
|
||||
comp4 = NEW #( `world` ) ).
|
||||
|
||||
DATA(itab) = VALUE it_type( ( struct )
|
||||
( comp1 = `Hi`
|
||||
comp2 = 2
|
||||
comp3 = VALUE #( ( `x` ) ( `y` ) ( `z` ) )
|
||||
comp4 = NEW #( `ABAP` ) ) ).
|
||||
|
||||
out->write( struct ).
|
||||
out->write( data = itab name = `itab` ).
|
||||
ENDMETHOD.
|
||||
ENDCLASS.
|
||||
```
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td> <code>CL_DEMO_CLASSRUN</code> </td>
|
||||
<td>
|
||||
As an alternative to using the <code>IF_OO_ADT_CLASSRUN</code> interface for displaying output in the console, you can also use the <code>CL_DEMO_CLASSRUN</code> class, which offers more methods.
|
||||
For more information, refer to <a href="https://blogs.sap.com/2023/10/24/abap-console-reloaded/">this blog</a>.
|
||||
The following example makes use of the <code>CL_DEMO_CLASSRUN</code> class. A structure and an internal table are displayed in the console. A structure component is a reference variable, which is automatically dereferenced. Plus, the <code>write_xml</code> method is shown, which displays XML data.
|
||||
<br><br>
|
||||
<br>
|
||||
|
||||
``` abap
|
||||
CLASS zcl_demo_abap DEFINITION
|
||||
@@ -175,10 +190,90 @@ ENDCLASS.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> <code>CL_XCO_CP_ADT_SIMPLE_CLASSRUN</code> </td>
|
||||
<td>
|
||||
|
||||
XCO alternative for output in the ADT console
|
||||
|
||||
<br>
|
||||
|
||||
``` abap
|
||||
CLASS zcl_demo_abap DEFINITION
|
||||
PUBLIC
|
||||
INHERITING FROM cl_xco_cp_adt_simple_classrun
|
||||
FINAL
|
||||
CREATE PUBLIC .
|
||||
|
||||
PUBLIC SECTION.
|
||||
PROTECTED SECTION.
|
||||
METHODS: main REDEFINITION.
|
||||
PRIVATE SECTION.
|
||||
ENDCLASS.
|
||||
|
||||
CLASS zcl_demo_abap IMPLEMENTATION.
|
||||
METHOD main.
|
||||
out->write( `Hello world` ).
|
||||
ENDMETHOD.
|
||||
ENDCLASS.
|
||||
```
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
|
||||
<p align="right"><a href="#top">⬆️ back to top</a></p>
|
||||
|
||||
## Creating and Transforming UUIDs
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td> Class </td> <td> Details/Code Snippet </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> <code>CL_SYSTEM_UUID</code> </td>
|
||||
<td>
|
||||
Creating and and converting system UUIDs with various algorithms
|
||||
<br><br>
|
||||
|
||||
``` abap
|
||||
"Creating UUIDs in binary format (16 bytes)
|
||||
TRY.
|
||||
DATA(uuid) = cl_system_uuid=>create_uuid_x16_static( ) .
|
||||
CATCH cx_uuid_error.
|
||||
ENDTRY.
|
||||
|
||||
"e.g. B2B012691AC31EDEADA0A495A7130961
|
||||
```
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> <code>XCO_CP_UUID</code> </td>
|
||||
<td>
|
||||
Transforming between different UUID formats
|
||||
<br><br>
|
||||
|
||||
``` abap
|
||||
DATA(uuid_c36) = xco_cp_uuid=>format->c36->to_uuid( '7cd44fff-036a-4155-b0d2-f5a4dfbcee92' ).
|
||||
|
||||
"7CD44FFF036A4155B0D2F5A4DFBCEE92
|
||||
DATA(uuid_c36_to_c32) = CONV sysuuid_c32( xco_cp_uuid=>format->c32->from_uuid( uuid_c36 ) ).
|
||||
|
||||
"7cd44fff-036a-4155-b0d2-f5a4dfbcee92
|
||||
DATA(uuid_c32_to_c36) = to_lower( CONV sysuuid_c36( xco_cp_uuid=>format->c36->from_uuid( uuid_c36 ) ) ).
|
||||
```
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p align="right"><a href="#top">⬆️ back to top</a></p>
|
||||
|
||||
|
||||
|
||||
## RAP
|
||||
|
||||
<table>
|
||||
@@ -519,7 +614,7 @@ DATA(random_num2) = cl_abap_random_int=>create( seed = cl_abap_random=>seed( )
|
||||
|
||||
<br>
|
||||
|
||||
The following example explores the generation of arbitraty numeric values.
|
||||
The following example explores the generation of arbitrary numeric values.
|
||||
- It uses dynamic programming techniques. Find more information in the [Dynamic Programming](06_Dynamic_Programming.md) cheat sheet.
|
||||
- The class names are constructed dynamically. They all begin with `CL_ABAP_RANDOM_`.
|
||||
- An object is created dynamically based on the constructed class name.
|
||||
@@ -5030,8 +5125,7 @@ CLASS zcl_demo_abap IMPLEMENTATION.
|
||||
ENDIF.
|
||||
CATCH cx_apj_dt_content INTO DATA(error_jtempl_del).
|
||||
DATA(jtempl_del_error_msg) = error_jtempl_del->get_longtext( ).
|
||||
out->write( jtempl_del_error_msg ).
|
||||
RETURN.
|
||||
out->write( jtempl_del_error_msg ).
|
||||
ENDTRY.
|
||||
|
||||
*&---------------------------------------------------------------------*
|
||||
@@ -5049,8 +5143,7 @@ CLASS zcl_demo_abap IMPLEMENTATION.
|
||||
|
||||
CATCH cx_apj_dt_content INTO DATA(error_jcat_del).
|
||||
DATA(jcat_del_error_msg) = error_jcat_del->get_text( ).
|
||||
out->write( jcat_del_error_msg ).
|
||||
RETURN.
|
||||
out->write( jcat_del_error_msg ).
|
||||
ENDTRY.
|
||||
ENDIF.
|
||||
|
||||
|
||||
@@ -482,6 +482,7 @@ The following example creates two DDIC database tables exploring several options
|
||||
|
||||
}
|
||||
```
|
||||
- Note: The numeric specification `abap.string(0);` for a component with type `string` (and also `rawstring`) means to specify the maximum length of the component. `0` in `abap.string(0);` means there is no restriction, `256` in `abap.string(256);` means restricting the length to 256. This restriction is checked in read and write operations.
|
||||
- Save and activate.
|
||||
- Proceed as above and create another DDIC database table using the name *ZDEMO_ABAP_TABL2*.
|
||||
- Insert the following code. The example includes a flat DDIC structure (created above) using the `include` specification. In doing so, you can avoid an extra declaration of table fields.
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
- [Components of Exception Classes](#components-of-exception-classes)
|
||||
- [Raising Class-Based Exceptions](#raising-class-based-exceptions)
|
||||
- [Handling Exceptions Using TRY Control Structures](#handling-exceptions-using-try-control-structures)
|
||||
- [TRY Control Structures](#try-control-structures)
|
||||
- [CATCH ... INTO ...: Storing Exception Objects and Evaluation](#catch--into--storing-exception-objects-and-evaluation)
|
||||
- [CLEANUP Statements](#cleanup-statements)
|
||||
- [RETRY Statements](#retry-statements)
|
||||
@@ -249,6 +250,7 @@ Example:
|
||||
- `is_resumable`: Flag for [resumable exceptions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenresumable_exception_glosry.htm); indicates whether the exception can be resumed and leave a `CATCH BEFORE UNWIND` block
|
||||
|
||||
> **💡 Note**<br>
|
||||
> - Further additions may be available depending on the exception object.
|
||||
> - Usually, instances of exception classes are created when exceptions are raised. However, instances can also be created programmatically, e.g., with the `NEW` operator (if the classes are not abstract).
|
||||
> - It is possible to define additional methods and attributes in exception classes, for example, for passing more information about error situations to handlers. Custom attributes should be defined as `READ-ONLY`.
|
||||
> - Find examples in the section below, covering `CATCH ... INTO ...`.
|
||||
@@ -337,6 +339,8 @@ ENDDO.
|
||||
|
||||
### Handling Exceptions Using TRY Control Structures
|
||||
|
||||
#### TRY Control Structures
|
||||
|
||||
- Exceptions can be handled locally using [`TRY`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abaptry.htm) control structures
|
||||
- To be prepared for potential exceptions that are raised when executing statements, statements can be included and executed within such a `TRY` control structure representing a *protected area*.
|
||||
- In doing so, it is possible for the ABAP runtime framework to catch exceptions, and you can react on error situations.
|
||||
|
||||
@@ -52,7 +52,7 @@ ABAP cheat sheets[^1] ...
|
||||
- In order to have all ABAP cheat sheet documents in one place, the *main* branch (for examples to be imported into the SAP BTP ABAP environment) also contains the ABAP cheat sheet documents that are only relevant for classic ABAP.
|
||||
- The example classes contained in the branches for classic ABAP mostly use syntax that is also available in ABAP for Cloud Development. Only the `TEST_ABAP_CHEAT_SHEETS_CLASSIC` subpackage contains syntax relevant to Standard ABAP and that is not available in ABAP for Cloud Development, such as dynpro-related ABAP keywords.
|
||||
- The code snippets in the ABAP cheat sheet documents and the executable examples include many comments. While it is generally not recommended to overuse comments in your code, they are used here to explain and provide context directly where it is needed. In many cases, they illustrate the results of ABAP statements.
|
||||
- As previously mentioned, the cheat sheet documents and examples primarily focus on syntax options. The usage and names of data objects, classes, methods etc. are nonsemantic.
|
||||
- As previously mentioned, the cheat sheet documents and examples primarily focus on syntax options. Most of the executable examples, code snippets, names of data objects, classes, methods, interfaces, etc., are nonsemantic.
|
||||
- Many ABAP statements allow additions in various orders, and these orders are not always fixed.
|
||||
</details>
|
||||
|
||||
@@ -224,6 +224,7 @@ Use the standalone version of the abapGit report to import the demo examples of
|
||||
## ⚡ Known Issues
|
||||
- Only one user on the system can import this repository because all object names must be globally unique.
|
||||
- Regarding possible code check warnings, e.g. for the many strings in the code, not using an `ORDER BY` clause, or messages regarding using `SELECT *`, the code deliberately avoids [pragmas](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenpragma_glosry.htm) and [pseudo comments](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenpseudo_comment_glosry.htm) in order to focus on the available ABAP syntax. See also the [Disclaimer](#%EF%B8%8F-disclaimer).
|
||||
- Importing the `main` branch in a system other than the SAP BTP ABAP Environment may cause errors in various cases. ABAP keywords, additions, and syntax options may not yet be available in the ABAP release. You can check the ABAP Release News in the ABAP Keyword Documentation.
|
||||
- Regarding the examples to be imported into a system supporting classic ABAP (where Standard ABAP is supported), note the following: In most cases, the cheat sheet documents and examples focus on ABAP for Cloud Development. Therefore, the lower the [ABAP release](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_release_glosry.htm) in your system, the fewer syntax options and examples are available. For example, the RAP examples need at least ABAP version 7.56. Or, the [`FINAL` declaration operator](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenfinal_inline.htm) is not available in ABAP version 7.56. The code examples in the classic ABAP branches do not necessarily reflect all (described) syntax variations and options that are available in classic ABAP and in the particular ABAP release. For more information on new ABAP features by release, see the ABAP Release News:
|
||||
- [ABAP Release News](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abennews.htm) for ABAP for Cloud Development. Note the ABAP release cycles listed there.
|
||||
- For Standard ABAP, see the ABAP relese news [here](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abennews.htm).
|
||||
@@ -256,6 +257,6 @@ This is not intended to be a contribution repository, so please do not create pu
|
||||
<br>
|
||||
|
||||
## 📜 License
|
||||
Copyright (c) 2024 SAP SE or an SAP affiliate company. All rights reserved. This project is licensed under the Apache Software License, version 2.0 except as noted otherwise in the [LICENSE](LICENSE) file.
|
||||
Copyright (c) 2025 SAP SE or an SAP affiliate company. All rights reserved. This project is licensed under the Apache Software License, version 2.0 except as noted otherwise in the [LICENSE](LICENSE) file.
|
||||
|
||||
[^1]: "A written [...] aid (such as a sheet of notes) that can be referred to for help in understanding or remembering something complex" (Definition for "cheat sheet" in Merriam-Webster Dictionary).
|
||||
@@ -512,7 +512,7 @@ CLASS zcl_demo_abap_xml_json IMPLEMENTATION.
|
||||
|
||||
LOOP AT attributes INTO DATA(attribute).
|
||||
APPEND VALUE #( node_type = `attribute`
|
||||
name = open_element->qname-name
|
||||
name = attribute->qname-name
|
||||
value = SWITCH #( attribute->value_type WHEN if_sxml_value=>co_vt_text THEN attribute->get_value( ) )
|
||||
) TO nodes_tab.
|
||||
ENDLOOP.
|
||||
@@ -521,7 +521,7 @@ CLASS zcl_demo_abap_xml_json IMPLEMENTATION.
|
||||
DATA(close_element) = CAST if_sxml_close_element( node_oo ).
|
||||
|
||||
APPEND VALUE #( node_type = `close element`
|
||||
name = open_element->qname-name
|
||||
name = close_element->qname-name
|
||||
) TO nodes_tab.
|
||||
|
||||
WHEN if_sxml_node=>co_nt_value.
|
||||
|
||||
Reference in New Issue
Block a user