Reputation: 2738
I want to read arbitrary ABAP data into an iXML
document object which contains the JSON-XML
representation of these data.
The only way I see is a double application of the id
transformation which is not very efficient:
data(lo_aux1) = cl_sxml_string_writer=>create( if_sxml=>co_xt_json ).
call transformation id
source data = ls_some_abap_data
result xml lo_aux1.
data(lv_aux2) = lo_aux1->get_output( ).
data(lo_result) = cl_ixml=>create( )->create_document( ).
call transformation id
source xml lv_aux2
result xml lo_result.
Now lo_result
is an iXML
DOM representation of the ABAP data in the JSON-XML
format, as required. Is it possible to obtain it in a more direct way?
Note: I am not interested in result objects of the sXML
family, as I want to manipulate / extend the resulting JSON-XML
document with the usual XML DOM methods, which is impossible for an sXML
writer object (sXML
writers are so simple they can only write everything they have into an output object, but don't allow editing of parts of the object that they already contain).
Upvotes: 2
Views: 1424
Reputation: 10621
I am sitting at a proxy and want to enrich the incoming JSON payload by some ABAP data, before passing it to the endpoint. Strategy: parse the incoming JSON into an JSON-XML doc, read the (complex) ABAP data into a second XML doc, then add XML subtrees of the second to the first before finally producing the result JSON from the first JSON-XML doc
I don't understand the need of iXML at all here. Converting complex ABAP structure into XML to merge it with JSON is redundant here. Let's assume you received some JSON data from Web-Service:
{
"main":{
"PASSENGERS":[
{
"NAME":"Horst",
"TITLE":"Herr",
"AGE":30
},
{
"NAME":"Jutta",
"TITLE":"Frau",
"AGE":35
},
{
"NAME":"Ingo",
"TITLE":"Herr",
"AGE":31
}
]
}
}
And you want enrich each passenger data with flight data from SFLIGHT
table. You can manipulate the nodes and attributes with cl_sxml_string_writer
just like this:
DATA(lv_json) = CONV string( '{"main": {"PASSENGERS":[ {"NAME":"Horst","TITLE":"Herr","AGE":30}, {"NAME":"Jutta","TITLE":"Frau","AGE":35}, {"NAME":"Ingo","TITLE":"Herr","AGE":31} ]}}' ).
DATA open_element TYPE REF TO if_sxml_open_element.
DATA value TYPE REF TO if_sxml_value_node.
DATA(o_json) = cl_abap_codepage=>convert_to( lv_json ).
DATA(reader) = cl_sxml_string_reader=>create( o_json ).
SELECT DISTINCT connid, fldate, planetype FROM sflight INTO TABLE @DATA(lt_flight).
DATA(xml) = cl_abap_codepage=>convert_to( lv_json ).
DATA(out) = cl_demo_output=>new( )->begin_section( 'Original JSON' )->write_xml( xml ).
DATA(writer) = CAST if_sxml_writer( cl_sxml_string_writer=>create( ) ).
open_element = writer->new_open_element( name = 'flights' nsuri = reader->nsuri ).
writer->write_node( open_element ).
DATA(i) = 1.
DO.
DATA(node) = reader->read_next_node( ).
IF node IS INITIAL.
EXIT.
ENDIF.
IF node IS INSTANCE OF if_sxml_value_node.
DATA(value_node) = CAST if_sxml_value_node( node ).
value_node->set_value( to_upper( value_node->get_value( ) ) ).
ENDIF.
writer->write_node( node ).
IF node->type = if_sxml_node=>co_nt_element_open.
DATA(op) = CAST if_sxml_open_element( node ).
CHECK op->qname-name = 'object' AND op->get_attributes( ) IS INITIAL.
open_element = writer->new_open_element( name = 'flight' nsuri = reader->nsuri ).
open_element->set_attribute( name = 'FLIGHT_DATE'
value = | { lt_flight[ i ]-fldate } | ).
open_element->set_attribute( name = 'PLANE_TYPE'
value = | { lt_flight[ i ]-planetype } | ).
writer->write_node( open_element ).
value = writer->new_value( ).
value->set_value( | { lt_flight[ i ]-connid } | ).
writer->write_node( value ).
writer->write_node( writer->new_close_element( ) ).
i = i + 1.
ENDIF.
ENDDO.
writer->write_node( writer->new_close_element( ) ).
out->next_section( 'Modified JSON'
)->write_xml(
CAST cl_sxml_string_writer( writer )->get_output( )
)->display( ).
DATA(result_json) = CAST cl_sxml_string_writer( writer )->get_output( ).
Resulted JSON will be dumped into result_json
variable and you can push it further wherever you want.
Here is resulted JSON, with capitalized passenger values and extended with flight
node, which contains flight number and attributed with data and plane type:
<flights>
<object>
<flight FLIGHT_DATE=" 20160610 " PLANE_TYPE=" A380‑800 "> 0002 </flight>
<object name="main">
<array name="PASSENGERS">
<object>
<flight FLIGHT_DATE=" 20160712 " PLANE_TYPE=" A380‑800 "> 0002 </flight>
<str name="NAME">HORST</str>
<str name="TITLE">HERR</str>
<num name="AGE">30</num>
</object>
<object>
<flight FLIGHT_DATE=" 20160813 " PLANE_TYPE=" A380‑800 "> 0002 </flight>
<str name="NAME">JUTTA</str>
<str name="TITLE">FRAU</str>
<num name="AGE">35</num>
</object>
<object>
<flight FLIGHT_DATE=" 20160914 " PLANE_TYPE=" A380‑800 "> 0002 </flight>
<str name="NAME">INGO</str>
<str name="TITLE">HERR</str>
<num name="AGE">31</num>
</object>
</array>
</object>
</object>
</flights>
Upvotes: 1