Saturday, May 26, 2012

Simple Transformation for XML in ABAP - Part III & some JSON on the side

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.
  1. For this example, a standard table type with complex structure is used. Accordingly you can create a ST program using editor :

  2. Generated ST Code [ Z_TEST_RAM ] is as below:

    <tt:transform xmlns:ddic="" xmlns:def="" xmlns:tt="">
      <tt:root name="LDAP_TABLE" type="ddic:LDAPALTAB">
          <tt:loop name="XALIAS0" ref=".LDAP_TABLE">
              <name tt:value-ref="NAME">
                <tt:loop ref="VALS">
                  <value tt:value-ref="$REF.VAL">
  3. 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.
    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 ).
    SOURCE XML gv_xml_xstring
    RESULT XML go_resstream.
    filename = 'C:\z_test_ram_xml_file.xml'
    xcontent = gv_final_xml_xstring ).

  4. Downloaded XML with encoding set as "UTF-16" is as below:
    <?xml version="1.0" encoding="UTF-16"?>
        <VALUE>How r you</VALUE>

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 :

  1. 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:call-template name="encode">
           <xsl:with-param name="input" select="$value"/>
    • 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:call-template name="encode">
           <xsl:with-param name="input" select="$value"/>
  2. 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.
        SOURCE XML gv_final_xml_xstring
    *    SOURCE ldap_table = lt_itab[]
        RESULT XML gv_json_string.
      WRITE : gv_json_string.
  3. Resultant JSONML is as below :
    ["LDAP_ATTRIBUTES",["LDAP_ATTRIBUTE",["NAME","header1"],["VALS",["VALUE","Hi"],["VALUE","How r you"]]]]
Warning : Please don't use above approach for any productive program without proper testing.  If you are looking for an ABAP/JSON library, for production use, then I would suggest to check ABAP JSON Library by Uwe Fetzer @se38 on SDN. Also just wanted to mention that Blogger's comment-section does not accept XML/HTML code hence you may need to escape any code before posting it in comments. [ Hint : search for "escape html tool online" in Google ]

Updated on 27/01/2013 :

Please refer to Horst Keller's Blog Post on SCN
Basically, you no longer need to try so much for JSON<->ABAP transformation as with new Releases 7.02 and 7.03/7.31 (Kernel-patch 116) JSON is supported natively in ABAP. Enjoy!.. and I hope you understand that these little improvements are big enablers :)

No comments:

Post a Comment

Info : Comments are reviewed before they are published. SPAMs are rejected.