Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions src/zcl_aff_test_types.clas.abap
Original file line number Diff line number Diff line change
Expand Up @@ -1028,6 +1028,29 @@ CLASS zcl_aff_test_types DEFINITION
enum_component TYPE c LENGTH 2,
END OF struc_with_own_enum_values.

CONSTANTS:
BEGIN OF co_enum_special_chars,
"! <p class="shorttext">Less Than</p>
"! Less than
less_than TYPE c LENGTH 1 VALUE '<',
"! <p class="shorttext">Greater Than</p>
"! Greater than
greater_than TYPE c LENGTH 1 VALUE '>',
"! <p class="shorttext">Ampersand</p>
"! Ampersand
ampersand TYPE c LENGTH 1 VALUE '&',
END OF co_enum_special_chars.

TYPES:
"! <p class="shorttext">Structure With Special Character Enum Values</p>
"! Structure with special character enum values
BEGIN OF struc_with_special_char_enums,
"! <p class="shorttext">Enum With Special Characters</p>
"! Enum with special characters
"! $values {@link zcl_aff_test_types.data:co_enum_special_chars }
special_char_enum TYPE c LENGTH 1,
END OF struc_with_special_char_enums.

CLASS-DATA subschema TYPE string_table.

CLASS-DATA expected_var TYPE REF TO data.
Expand Down
24 changes: 21 additions & 3 deletions src/zcl_aff_writer_xslt.clas.abap
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,12 @@ CLASS zcl_aff_writer_xslt DEFINITION
get_to_ref
IMPORTING
name TYPE string
RETURNING VALUE(result) TYPE string.
RETURNING VALUE(result) TYPE string,
escape_xml_chars
IMPORTING
value TYPE string
RETURNING
VALUE(result) TYPE string.


ENDCLASS.
Expand Down Expand Up @@ -459,16 +464,19 @@ CLASS zcl_aff_writer_xslt IMPLEMENTATION.

METHOD get_abap_value.
DATA abap_value_copy TYPE string.
DATA escaped_value TYPE string.
CASE element_description->type_kind.
WHEN cl_abap_typedescr=>typekind_int OR cl_abap_typedescr=>typekind_int1 OR
cl_abap_typedescr=>typekind_int2 OR cl_abap_typedescr=>typekind_int8.
abap_value_copy = abap_value.
CONDENSE abap_value_copy.
result = |I({ abap_value_copy })|.
WHEN cl_abap_typedescr=>typekind_num.
result = |N('{ abap_value }')|.
escaped_value = escape_xml_chars( abap_value ).
result = |N('{ escaped_value }')|.
WHEN OTHERS.
result = |'{ abap_value }'|.
escaped_value = escape_xml_chars( abap_value ).
result = |'{ escaped_value }'|.
ENDCASE.
ENDMETHOD.

Expand Down Expand Up @@ -811,4 +819,14 @@ CLASS zcl_aff_writer_xslt IMPLEMENTATION.
ENDLOOP.
ENDMETHOD.

METHOD escape_xml_chars.
result = value.
" Ampersand must be replaced first to avoid double-escaping
REPLACE ALL OCCURRENCES OF '&' IN result WITH '&#38;'.
REPLACE ALL OCCURRENCES OF '<' IN result WITH '&#60;'.
REPLACE ALL OCCURRENCES OF '>' IN result WITH '&#62;'.
REPLACE ALL OCCURRENCES OF '"' IN result WITH '&#34;'.
REPLACE ALL OCCURRENCES OF '''' IN result WITH '&#39;'.
ENDMETHOD.

Comment on lines +822 to +831
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't we use ABAP's built-in function escape to escape xml?

See https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/ABENESCAPE_FUNCTIONS.html

ENDCLASS.
70 changes: 70 additions & 0 deletions src/zcl_aff_writer_xslt.clas.testclasses.abap
Original file line number Diff line number Diff line change
Expand Up @@ -1297,6 +1297,7 @@ CLASS ltcl_type_writer_xslt_ad DEFINITION FINAL FOR TESTING
structure_with_enums FOR TESTING RAISING cx_static_check,
structure_with_default_problem FOR TESTING RAISING cx_static_check,
struc_with_own_enum_values FOR TESTING RAISING cx_static_check,
struc_with_special_char_enums FOR TESTING RAISING cx_static_check,
enable_extension FOR TESTING RAISING cx_static_check.
ENDCLASS.

Expand Down Expand Up @@ -2566,6 +2567,39 @@ CLASS ltcl_type_writer_xslt_ad IMPLEMENTATION.
validate_output( act_output ).
ENDMETHOD.

METHOD struc_with_special_char_enums.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Integration test in ltcl_integration_test_ad missing

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Integration test in ltcl_integration_test_ad missing

@copilot

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added integration test struc_with_special_char_enums in ltcl_integration_test_ad that tests round-trip serialization/deserialization for all three special characters (<, >, &). Commit: 5fb3ed0

DATA test_type TYPE zcl_aff_test_types=>struc_with_special_char_enums.
DATA(act_output) = test_generator->generate_type( test_type ).
me->exp_transformation = VALUE #(
( `<tt:cond>` )
( ` <object>` )
( ` <tt:group>` )
( ` <tt:cond s-check="not-initial(SPECIAL_CHAR_ENUM)" frq="?">` )
( ` <str name="specialCharEnum">` )
( ` <tt:value ref="SPECIAL_CHAR_ENUM" map="` )
( ` val('&#60;')=xml('lessThan'),` )
( ` val('&#62;')=xml('greaterThan'),` )
( ` val('&#38;')=xml('ampersand')"` )
( ` />` )
( ` </str>` )
( ` </tt:cond>` )
( ` <tt:d-cond frq="*">` )
( ` <_ tt:lax="on">` )
( ` <tt:call-method class="CL_AFF_XSLT_CALLBACK_TYPE" name="RAISE_DIFFERENT_TYPE_EXCEPTION" reader="IO_READER">` )
( ` <tt:with-parameter name="MEMBERS" val="'specialCharEnum;'"/>` )
( ` </tt:call-method>` )
( ` <tt:skip/>` )
( ` </_>` )
( ` </tt:d-cond>` )
( ` <tt:d-cond frq="?">` )
( ` <__/>` )
( ` </tt:d-cond>` )
( ` </tt:group>` )
( ` </object>` )
( `</tt:cond>` ) ).
validate_output( act_output ).
ENDMETHOD.

METHOD validate_output.
DATA exp TYPE string_table.

Expand Down Expand Up @@ -2653,6 +2687,8 @@ RISK LEVEL DANGEROUS.

struc_with_own_enum_values FOR TESTING RAISING cx_static_check,

struc_with_special_char_enums FOR TESTING RAISING cx_static_check,

from_abap_to_json
IMPORTING
test_type TYPE data
Expand Down Expand Up @@ -3224,6 +3260,40 @@ CLASS ltcl_integration_test_ad IMPLEMENTATION.
act_data = test_type ).
ENDMETHOD.

METHOD struc_with_special_char_enums.
DATA test_type TYPE zcl_aff_test_types=>struc_with_special_char_enums.
test_type = VALUE #( special_char_enum = '<' ).
exp_json = VALUE #(
( `{` )
( ` "specialCharEnum": "lessThan"` )
( `}` ) ).
do_integration_test(
EXPORTING
test_type = test_type
CHANGING
act_data = test_type ).
test_type = VALUE #( special_char_enum = '>' ).
exp_json = VALUE #(
( `{` )
( ` "specialCharEnum": "greaterThan"` )
( `}` ) ).
do_integration_test(
EXPORTING
test_type = test_type
CHANGING
act_data = test_type ).
test_type = VALUE #( special_char_enum = '&' ).
exp_json = VALUE #(
( `{` )
( ` "specialCharEnum": "ampersand"` )
( `}` ) ).
do_integration_test(
EXPORTING
test_type = test_type
CHANGING
act_data = test_type ).
ENDMETHOD.

METHOD do_integration_test.
from_abap_to_json(
EXPORTING
Expand Down
Loading