This is just to explain a bit further on one of my comments from the earlier XML related post : Generate Simple Transformation for XML in ABAP - Part II.
There were a few questions regarding transforming ABAP ITABs with deep structures to XML and setting encoding ( other than default UTF-8 ) for the output XML etc.
Initial steps are similar to the example in my last XML related posts.
- For this example, a standard table type with complex structure is used. Accordingly you can create a ST program using editor :
- Generated ST Code [ Z_TEST_RAM ] is as below:
<tt:transform xmlns:ddic="http://www.sap.com/abapxml/types/dictionary" xmlns:def="http://www.sap.com/abapxml/types/defined" xmlns:tt="http://www.sap.com/transformation-templates"> <tt:root name="LDAP_TABLE" type="ddic:LDAPALTAB"> <tt:template> <ldap_attributes> <tt:loop name="XALIAS0" ref=".LDAP_TABLE"> <ldap_attribute> <name tt:value-ref="NAME"> <vals> <tt:loop ref="VALS"> <value tt:value-ref="$REF.VAL"> </value></tt:loop> </vals> </name></ldap_attribute> </tt:loop> </ldap_attributes> </tt:template> </tt:root></tt:transform>
- ABAP Sample Code is as below :
REPORT z_test_ram_xml. * complex structure example DATA : lt_itab TYPE ldapaltab, wa_itab LIKE LINE OF lt_itab , lt_val TYPE valtabc, wa_val LIKE LINE OF lt_val . DATA: gv_xml_xstring TYPE xstring. DATA: gv_final_xml_xstring TYPE xstring. * <<< Populate Example data in complex struture itab wa_itab-name = 'header1'. wa_val-val = 'Hi'. APPEND wa_val TO wa_itab-vals. wa_val-val = 'How r you'. APPEND wa_val TO wa_itab-vals. APPEND wa_itab TO lt_itab. *>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> * This is the main ST call. CALL TRANSFORMATION z_test_ram SOURCE ldap_table = lt_itab[] RESULT XML gv_xml_xstring. *>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> * Now a Bit of cheating - to get the encoding we'll use standard XSLT ID * rather than ST - not required if you need Default UTF-8 from ST DATA :go_ixml TYPE REF TO if_ixml, go_stream_factory TYPE REF TO if_ixml_stream_factory, go_encoding TYPE REF TO if_ixml_encoding, go_resstream TYPE REF TO if_ixml_ostream. CONSTANTS: gc_encoding TYPE string VALUE 'UTF-16'. "or UTF-8 etc. go_ixml = cl_ixml=>create( ). go_stream_factory = go_ixml->create_stream_factory( ). go_encoding = go_ixml->create_encoding( character_set = gc_encoding byte_order = 0 ). go_resstream = go_stream_factory->create_ostream_XSTRING( gv_final_xml_xstring ). CALL METHOD go_resstream->set_encoding( go_encoding ). CALL TRANSFORMATION ID SOURCE XML gv_xml_xstring RESULT XML go_resstream. cl_salv_data_services=>download_xml_to_file( filename = 'C:\z_test_ram_xml_file.xml' xcontent = gv_final_xml_xstring ).
- Downloaded XML with encoding set as "UTF-16" is as below:
<?xml version="1.0" encoding="UTF-16"?> <LDAP_ATTRIBUTES> <LDAP_ATTRIBUTE> <NAME>header1</NAME> <VALS> <VALUE>Hi</VALUE> <VALUE>How r you</VALUE> </VALS> </LDAP_ATTRIBUTE> </LDAP_ATTRIBUTES>
By the way, I was experimenting with an XML to JSON converter( rather JSONML ) that is compatible with XSLT-1.0 hence it can be used with ABAP XSLT . I've not tested it properly yet but just to add some information: The XSLT is written by @bramstein and the code can be taken from here . Some details are on this can be found here. Steps are as below :
- Created an XSLT program in XSLT_TOOL with Name(ID) Z_RAM_TEST_XSLT_JSON .
- For the XSLT, get the code from here .
- Just changed a few lines due to some syntax issue, from this:
<xsl:when test="(normalize-space($value) ne $value or string(number($value)) = 'NaN' or (substring($value , string-length($value), 1) = '.') or (substring($value, 1, 1) = '0') and not($value = '0')) and not($value = 'false') and not($value = 'true') and not($value = 'null')"> <xsl:text>"</xsl:text> <xsl:call-template name="encode"> <xsl:with-param name="input" select="$value"/> </xsl:call-template> <xsl:text>"</xsl:text> </xsl:when>
- To :
<xsl:when test="(normalize-space($value) != $value or string(number($value)) = 'NaN' or (substring($value , string-length($value), 1) = '.') or (substring($value, 1, 1) = '0') and not($value = '0')) and not($value = 'false') and not($value = 'true') and not($value = 'null')"> <xsl:text>"</xsl:text> <xsl:call-template name="encode"> <xsl:with-param name="input" select="$value"/> </xsl:call-template> <xsl:text>"</xsl:text> </xsl:when>
- Added following piece of code at the end of the ABAP program (z_test_ram_xml) :
[ Note that it might work directly from from ABAP Itab to JSON but there were some unwanted asx:abap tags appearing on the first line. That can be sorted out though. ]
*<<<< Convert the output XML to JSON using XSLT DATA : gv_json_string TYPE STRING. CALL TRANSFORMATION Z_RAM_TEST_XSLT_JSON SOURCE XML gv_final_xml_xstring * SOURCE ldap_table = lt_itab[] RESULT XML gv_json_string. WRITE : gv_json_string.
- Resultant JSONML is as below :
["LDAP_ATTRIBUTES",["LDAP_ATTRIBUTE",["NAME","header1"],["VALS",["VALUE","Hi"],["VALUE","How r you"]]]]
Hello Ram,
ReplyDeleteThanks for these helpful blog for simple transformations. because of this i am able to generate xml file successfully. But i am having problem and i am unable to find solution.
Let's say i am having deep structure created in SE11 (and that is also being used in call transformation) having one field 'Header' - deep structure and second field is 'Info' type table .
Now if my xml is generated for multiple line items records in 'Info' table then all line items are showing under one main 'Info' node .
i want to generate 'Info' node for my each line item.
Do you have any idea how we can achieve this using simple transformation ?
Thanks