HeiDoc.net: The Technology Treasure Chest

User Rating: 5 / 5

Star ActiveStar ActiveStar ActiveStar ActiveStar Active
 

Some time ago, I was looking for some demonstration how to get data from SAP into an XML file and vice versa, but found nothing satisfactory on the web. So I had to start developing the "try and error" method. By now, I believe, I've gathered enough knowledge to write that tutorial myself. Well, here it comes, and with it the complete ABAP and XSLT source code, and hopefully enough explanation that you'll be able to develop an understanding what is happening, and to use it for your own projects.

Part 1: XML to ABAP

To get started, we first of all need a structure within SAP that has to be mapped onto certain XML elements and vice versa. We want to keep things very simple, so let's say a data set shall be of a type person with the fields customer_id, first_name and last_name.

It's easy to put this into an ABAP type:

TYPES: BEGIN OF ts_person,
         cust_id(4)    TYPE n,
         firstname(20) TYPE c,
         lastname(20)  TYPE c,
       END OF ts_person.

It's also easy to think of an XML structure that can contain data of this type:

<?xml version="1.0" encoding="iso-8859-1" ?>
<CUSTOMERS>
  <PERSON>
    <customer_id>1</customer_id>
    <first_name>Jan</first_name>
    <last_name>Krohn</last_name>
  </PERSON>
  <PERSON>
    <customer_id>2</customer_id>
    <first_name>James</first_name>
    <last_name>Kirk</last_name>
  </PERSON>
</CUSTOMERS>

And now we're going to shift the data from the above XML file into an internal ABAP table of the type ts_person. The ABAP report to accomplish this task consists of two parts. The first part is a regular ABAP programme, the second part is an XSLT transformation. SAP supports this standard via CALL TRANSFORMATION. But more about that later.

Now copy the following code into your ABAP editor, and do read the comments to understand what's going on:

*-------------------------------------------------------------------*
*  Report Z_XML_TO_ABAP                                             *
*                                                                   *
*-------------------------------------------------------------------*
*  Read the data from an XML file into an ABAP internal table,      *
*  and print it on the screen                                       *
*-------------------------------------------------------------------*

REPORT z_xml_to_abap.

TYPE-POOLS abap.

CONSTANTS gs_file TYPE string VALUE ´C:\temp\customers.xml´.

* This is the structure for the data from the XML file

TYPES: BEGIN OF ts_person,
         cust_id(4)    TYPE n,
         firstname(20) TYPE c,
         lastname(20)  TYPE c,
       END OF ts_person.

* Table for the XML content

DATA: gt_itab       TYPE STANDARD TABLE OF char2048.

* Table and work ares for the data from the XML file

DATA: gt_person     TYPE STANDARD TABLE OF ts_person,
      gs_person     TYPE ts_person.

* Result table that contains references
* of the internal tables to be filled

DATA: gt_result_xml TYPE abap_trans_resbind_tab,
      gs_result_xml TYPE abap_trans_resbind.

* For error handling

DATA: gs_rif_ex     TYPE REF TO cx_root,
      gs_var_text   TYPE string.

* Get the XML file from your client

CALL METHOD cl_gui_frontend_services=>gui_upload
  EXPORTING
    filename                = gs_file
  CHANGING
    data_tab                = gt_itab
  EXCEPTIONS
    file_open_error         = 1
    file_read_error         = 2
    no_batch                = 3
    gui_refuse_filetransfer = 4
    invalid_type            = 5
    no_authority            = 6
    unknown_error           = 7
    bad_data_format         = 8
    header_not_allowed      = 9
    separator_not_allowed   = 10
    header_too_long         = 11
    unknown_dp_error        = 12
    access_denied           = 13
    dp_out_of_memory        = 14
    disk_full               = 15
    dp_timeout              = 16
    not_supported_by_gui    = 17
    error_no_gui            = 18
    OTHERS                  = 19.

IF sy-subrc <> 0.
  MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
          WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.

* Fill the result table with a reference to the data table.
* Within the XSLT stylesheet, the data table can be accessed with
* "IPERSON".

GET REFERENCE OF gt_person INTO gs_result_xml-value.
gs_result_xml-name = ´IPERSON´.
APPEND gs_result_xml TO gt_result_xml.

* Perform the XSLT stylesheet

TRY.
    CALL TRANSFORMATION z_xml_to_abap
    SOURCE XML gt_itab
    RESULT (gt_result_xml).

CATCH cx_root INTO gs_rif_ex.

    gs_var_text = gs_rif_ex->get_text( ).
    MESSAGE gs_var_text TYPE ´E´.

ENDTRY.

* Now let´s see what we got from the file

LOOP AT gt_person INTO gs_person.
  WRITE: / ´Customer ID:´, gs_person-cust_id.
  WRITE: / ´First name :´, gs_person-firstname.
  WRITE: / ´Last name  :´, gs_person-lastname.
  WRITE : /.
ENDLOOP. "gt_person.

Now we can launch the SAP XSLT editor by double clicking on the transformation z_xml_to_abap. Depending on your SAP system, you'll have to choose the transformation type. XSLT is correct here. You'll see that SAP has already created a simple XSLT frame. Replace it with the following stylesheet:

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output encoding="iso-8859-1" indent="yes" method="xml" version="1.0"/>
  <xsl:strip-space elements="*"/>

  <xsl:template match="/">
    <asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
      <asx:values>
        <IPERSON>
          <xsl:apply-templates select="//PERSON"/>
        </IPERSON>
      </asx:values>
    </asx:abap>
  </xsl:template>

  <xsl:template match="PERSON">
    <item>
      <CUST_ID>
        <xsl:value-of select="customer_id"/>
      </CUST_ID>
      <FIRSTNAME>
        <xsl:value-of select="first_name"/>
      </FIRSTNAME>
      <LASTNAME>
        <xsl:value-of select="last_name"/>
      </LASTNAME>
    </item>
  </xsl:template>

</xsl:transform>

XSLT is an internet standard developed by the W3 consortium. It's supported by recent versions of most internet applications and programming suites. For example, it's included in Internet Explorer, Firefox, .NET and Java. Whereas XSLT version 1.0 can't do much more than transforming XML files from one format into another, XSLT version 2.0 can be used to solve simple programming tasks. That newer version, however, isn't supported by SAP yet.

When transforming data from or to the ABAP format, a special XML dialect called ABAP-XML is used. The SAP kernel then converts this format into ABAP internal tables or the internal tables to ABAP-XML.

Now the first part is done. This programme will successfully extract the data from the XML file and import it in an internal table. Try it by saving the XML example file in the location C:\temp\customers.xml and run the report. You can also try to alter the XSLT and the XML file, and see how it affects the result.

Part 2: ABAP to XML

The other direction from ABAP to XML works exactly the other way around. Again, we're using the type definition and the XML structure from part 1. We're appending a couple of test values to the internal table, and apply another XSLT transformation to this data. Copy the following source code into your ABAP editor, and don't forget to read the comments:

*-------------------------------------------------------------------*
*  Report Z_ABAP_TO_XML                                             *
*                                                                   *
*-------------------------------------------------------------------*
*  Write the data from an internal ABAP table into an XML document, *
*  and write it onto your frontend computer                         *
*-------------------------------------------------------------------*

REPORT z_abap_to_xml.

TYPE-POOLS: abap.

CONSTANTS gs_file TYPE string VALUE ´C:\temp\customers.xml´.
* This is the structure for the data to go into the XML file

TYPES: BEGIN OF ts_person,
  cust_id(4)    TYPE n,
  firstname(20) TYPE c,
  lastname(20)  TYPE c,
END OF ts_person.

* Table for the XML content

DATA: gt_itab        TYPE STANDARD TABLE OF char2048.

* Table and work area for the data to fill the XML file with

DATA: gt_person      TYPE STANDARD TABLE OF ts_person,
      gs_person      TYPE ts_person.

* Source table that contains references
* of the internal tables that go into the XML file

DATA: gt_source_itab TYPE abap_trans_srcbind_tab,
      gs_source_wa   TYPE abap_trans_resbind.

* For error handling

DATA: gs_rif_ex      TYPE REF TO cx_root,
      gs_var_text    TYPE string.

* Fill the internal table

gs_person-cust_id   = ´3´.
gs_person-firstname = ´Bill´.
gs_person-lastname  = ´Gates´.
APPEND gs_person TO gt_person.

gs_person-cust_id   = ´4´.
gs_person-firstname = ´Frodo´.
gs_person-lastname  = ´Baggins´.
APPEND gs_person TO gt_person.

* Fill the source table with a reference to the data table.
* Within the XSLT stylesheet, the data table can be accessed with
* "IPERSON".

GET REFERENCE OF gt_person INTO gs_source_wa-value.
gs_source_wa-name = ´IPERSON´.
APPEND gs_source_wa TO gt_source_itab.

* Perform the XSLT stylesheet

TRY.

    CALL TRANSFORMATION z_abap_to_xml
    SOURCE (gt_source_itab)
    RESULT XML gt_itab.

  CATCH cx_root INTO gs_rif_ex.

    gs_var_text = gs_rif_ex->get_text( ).
    MESSAGE gs_var_text TYPE ´E´.

ENDTRY.

* Download the XML file to your client

CALL METHOD cl_gui_frontend_services=>gui_download
  EXPORTING
    filename                = gs_file
  CHANGING
    data_tab                = gt_itab
  EXCEPTIONS
    file_write_error        = 1
    no_batch                = 2
    gui_refuse_filetransfer = 3
    invalid_type            = 4
    no_authority            = 5
    unknown_error           = 6
    header_not_allowed      = 7
    separator_not_allowed   = 8
    filesize_not_allowed    = 9
    header_too_long         = 10
    dp_error_create         = 11
    dp_error_send           = 12
    dp_error_write          = 13
    unknown_dp_error        = 14
    access_denied           = 15
    dp_out_of_memory        = 16
    disk_full               = 17
    dp_timeout              = 18
    file_not_found          = 19
    dataprovider_exception  = 20
    control_flush_error     = 21
    not_supported_by_gui    = 22
    error_no_gui            = 23
    OTHERS                  = 24.

IF sy-subrc <> 0.
  MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
  WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.

Of course, the second report also needs an XSLT stylesheet. Create it by double clicking the transformation. Then insert the following source code into the XSLT editor:

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

  <xsl:output encoding="iso-8859-1" indent="yes" method="xml" version="1.0"/>
  <xsl:strip-space elements="*"/>

  <xsl:template match="/">
    <CUSTOMERS>
      <xsl:apply-templates select="//IPERSON/item"/>
    </CUSTOMERS>
  </xsl:template>

  <xsl:template match="IPERSON/item">
    <item>
      <customer_id>
        <xsl:value-of select="CUST_ID"/>
      </customer_id>
      <first_name>
        <xsl:value-of select="FIRSTNAME"/>
      </first_name>
      <last_name>
        <xsl:value-of select="LASTNAME"/>
      </last_name>
    </item>
  </xsl:template>

</xsl:transform>

Now run your report. It'll create a valid XML file for you from the two lines of the internal table. Here you can also try to change the XSLT stylesheet, and see how your alterations affect the resulting XML file.

Final remarks

There are two more things I'd like to finally let you know. This tutorial has just shown you only the tip of the iceberg. We've used only a flat structure on the ABAP side, and the input/output XML format is also kind of flat. The XML formats in broad use are way more complex, just think of SVG, XHTML or the Microsoft Office XML files. XSLT can easily manage these complex formats as well, even from within SAP, and extract certain data from these files, or generate complex XML files containing data from the SAP tables.

The second issue I want to raise is of the code page. Of course, the code page of the XML files has to be the same one as the code page of the SAP system. Also, when downloading the generated XML file to your computer, you'll have to select the correct corresponding code page.

You can work around this restriction if you don't use string and char data types, but xstring and raw instead. In this case, you'll have to upload and download your files in binary type. It's even possible to create UTF-8 encoded XML files in a non-unicode SAP system! The examples in this tutorial are all made to work with SAP Netweaver Trial 7.02 SP6. It's possible that you'll have to adapt the choice of code pages if you want to run them on another system.

What I can offer for your company is more than three years of experience of XSLT integration in SAP, especially when it comes to generating complex XML files, or extracting data from XML files and storing it within SAP tables. I can also offer professional training for your IT department. Please get in touch and ask for a quote. Based in Cambodia, we can offer you high quality service at very good rates.

Get deeper into XSLT

Inside XSLT book

Although a bit old, but not the least outdated, the best XSLT tutorial and reference book I've come across is "Inside XSLT" by Steven Holzner. If you want to parse or build deeply nested XML documents, this book will help you understand XSLT in every aspect.

Every single XSLT element and XPath function is explained in detail with more than 400 code examples, for example, how to sort elements, how to use loops and if conditions, and how to convert data to other formats like HTML.