Skip to Content
Author's profile photo Kirill Smirnov

XML Schema Import Into an ABAP system

It sometimes happens… You do not have an SAP PI instance (or something similar), however you need to download (or upload) an XML file, and it is very hard to control the file structure. All you have is an XML schema provided by an external system, and there is a challenge – to re-create in SAP something similar to the file format described in the XSD. And remember – no SAP PI or other Integration Bus capable of doing the import on your behalf!

This tiny utility uses standard SAP ABAP Proxy mechanism to import the data definition and create respective DDIC objects. The process flow is very similar to Service Consumer creation in SPROXY transaction, however with this utility you can use directly use an XSD file (dummy WSDL is created automatically). The utility was also inspired by this blog –  http://sapblog.rmtiwari.com.

Please note that in order to make this post easier to read, I’ve omitted some basic routines (e.g. for file selection dialogue, message output etc.).

Global data and selection-screen:

*&---------------------------------------------------------------------*
 *& Report  Z_IMPORT_XML_SCHEMA
 *&
 *&---------------------------------------------------------------------*
 *& This reports imports an XSD file and calls standard ABAP/4 proxy generation
 *& methods to (re-)create DDIC objects
 *&---------------------------------------------------------------------*

 REPORT  z_import_xml_schema.

 TYPE-POOLS: sprx,
             trwbo.
 CONSTANTS:
        gc_lcl TYPE packname VALUE '$TMP'.
 DATA:
      go_proxy    TYPE REF TO cl_proxy,
      gv_xcontent TYPE xstring,
      gv_wsdl     TYPE xstring.

 PARAMETERS:
           p_xsdfn TYPE anyuri OBLIGATORY VALUE CHECK. "XML Schema file name

 SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME.
 PARAMETERS:
           p_pckg  TYPE packname   VALUE CHECK DEFAULT gc_lcl, " Package
           p_trrq  TYPE trkorr     VALUE CHECK,                " Transport request
           p_prfx  TYPE prx_prefix OBLIGATORY DEFAULT 'Z',     " Prefix
           p_actv  AS CHECKBOX     default 'X'.                " Activate immediately
 SELECTION-SCREEN END OF BLOCK b1.

 " Transport request selection dialogue:

 AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_trrq.
   PERFORM get_transport_request CHANGING p_trrq. "

   " File name selection dialogue:

 AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_xsdfn.
   PERFORM get_file_name CHANGING p_xsdfn. " 

I have used the following sequence:

  1. File upload;
  2. Conversion to WSDL – format which is “native” for an ABAP/4 proxy generator;
  3. Instantiation of the proxy object – using a generated WSDL;
  4. DDIC update (and activation if desired);

Step 1 – File upload:

FORM upload_file USING    iv_filename TYPE anyuri
                  CHANGING cv_xcontent TYPE xstring.
   DATA: lo_slib_retriever TYPE REF TO if_slib_retriever,
         lo_exception      TYPE REF TO cx_root,
         lv_fault          TYPE xstring.

   TRY.
       lo_slib_retriever = cl_slib_entity_container=>create_retriever( ).
       cv_xcontent = lo_slib_retriever->get_content( iv_filename  ).
     CATCH cx_slib INTO lo_exception.
       PERFORM output_message USING 'E'
                                    'Unable to read the file specified.'(urf).
       STOP.
   ENDTRY.
 ENDFORM.                    "upload_file

Step 2 – WSDL conversion:

FORM xsd2wsdl USING    iv_xcontent TYPE xstring
               CHANGING cv_wsdl     TYPE xstring.

   DATA:
         lv_message   TYPE string,
         lx_gen_error TYPE REF TO cx_proxy_gen_error.

   TRY.
       CALL METHOD cl_proxy_test_utils=>xsd2wsdl
         EXPORTING
           schema = iv_xcontent
         RECEIVING
           wsdl   = cv_wsdl.
     CATCH cx_proxy_gen_error INTO lx_gen_error .
       lv_message = lx_gen_error->if_message~get_text( ).
       PERFORM output_message USING 'E'
                                     lv_message.
       STOP.
   ENDTRY.

 ENDFORM.                    "xsd2wsdl

Step 3 – Instantiation of a proxy object:

FORM init_proxy USING     iv_wsdl TYPE xstring
                           iv_pckg
                           iv_praefix
                 CHANGING  co_proxy TYPE REF TO cl_proxy.

   DATA:
        lx_root    TYPE REF TO cx_root,
        lv_message TYPE string.

   TRY.
       CALL METHOD cl_proxy_test_utils=>wsdl2proxy
         EXPORTING
           wsdl    = iv_wsdl
           package = iv_pckg
           praefix = iv_praefix
         RECEIVING
           proxy   = co_proxy.
     CATCH cx_proxy_gen_error INTO lx_root.
       " LX_ROOT is checked below
     CATCH cx_slib INTO lx_root.
       " LX_ROOT is checked below
     CATCH cx_sidl INTO lx_root.
       " LX_ROOT is checked below
   ENDTRY.

   IF lx_root IS BOUND.
     lv_message = lx_root->if_message~get_text( ).
     PERFORM output_message USING 'E'
                                   lv_message.
     STOP.
   ENDIF.

 ENDFORM.                    "init_proxy

Step 4 – DDIC update….

FORM save_proxy USING io_proxy TYPE REF TO cl_proxy.
   DATA:
        lx_error   TYPE REF TO cx_proxy_gen_error,
        lv_message TYPE string.

   TRY.
       CALL METHOD io_proxy->save
         CHANGING
           transport_number = p_trrq.
     CATCH cx_proxy_gen_error INTO lx_error .

       lv_message = lx_error->if_message~get_text( ).
       PERFORM output_message USING 'E'
                                     lv_message.
       STOP.

   ENDTRY.

   " No errors:
   PERFORM output_message USING 'S'
                                'Proxy was saved.'(pws).

 ENDFORM.                    "save_proxy

….and activation:

FORM activate_proxy USING io_proxy TYPE REF TO cl_proxy
                           iv_trreq TYPE trkorr .
   DATA:
        lt_objects TYPE sprx_log_t,
        lt_log     TYPE sprx_log_t,
        ls_objects LIKE LINE OF lt_objects,
        ls_log     LIKE LINE OF lt_log,
        lx_error   TYPE REF TO cx_proxy_gen_error,
        lv_message TYPE string.


   TRY.
       CALL METHOD io_proxy->activate
         EXPORTING
           activate_all      = 'X'
           deletion          = 'X'
         IMPORTING
           activated_objects = lt_objects
           log               = lt_log
         CHANGING
           transport_number  = iv_trreq.
     CATCH cx_proxy_gen_error INTO lx_error.
       lv_message = lx_error->if_message~get_text( ).
       PERFORM output_message USING 'E'
                                     lv_message.
       STOP.
   ENDTRY.

   IF NOT lt_log[] IS INITIAL.
     PERFORM output_message USING 'I'
                                  'Activation log:'(alo).
     LOOP AT lt_log INTO ls_log.

       MESSAGE ID      ls_log-msgid
               TYPE    ls_log-msgty
               NUMBER  ls_log-msgno
               WITH    ls_log-msgv1
                       ls_log-msgv2
                       ls_log-msgv3
                       ls_log-msgv4
                       INTO lv_message.
       PERFORM output_message USING ls_log-msgty
                                    lv_message.
     ENDLOOP.
   ENDIF.

   IF NOT lt_objects[] IS INITIAL.
     PERFORM output_message USING 'I'
                                'Activated objects:'(oli).
     LOOP AT lt_objects INTO ls_objects.

       MESSAGE ID      ls_objects-msgid
               TYPE    ls_objects-msgty
               NUMBER  ls_objects-msgno
               WITH    ls_objects-msgv1
                       ls_objects-msgv2
                       ls_objects-msgv3
                       ls_objects-msgv4
                       INTO lv_message.
       PERFORM output_message USING ls_objects-msgty
                                    lv_message.
     ENDLOOP.
   ENDIF.

If you prefer not to keep “redundant” development objects, feel free to delete the proxy itself (without deletion of the subsequent objects 🙂 ). However, it should affect nothing if the proxy definition is transported to the production environment.

At the end of the day, you will get the DDIC structures which correspond to the ones described in an XML schema. Now using those structures your potential XML Simple Transformations will be really simple.

Assigned Tags

      4 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Vlad Rinciog
      Vlad Rinciog

      Hello,

       

      Can you provide the entire code?

       

      For example, the missing performs:

       

      PERFORM get_transport_request CHANGING p_trrq.  PERFORM get_file_name CHANGING p_xsdfn. "

      PERFORM get_file_name CHANGING p_xsdfn.

       

      and  maybe what is missing?

       

      I need this for:

       

      I'm working on a request for Poland to make an adjustment for a legal requirement. I installed an OSS note and made all the customizing and now we are facing problems with the XML. I know that the XML is the full responsibility of the customer, but maybe someone has an idea how can we create an XML to export the date from the 3 tables. (This requirement contain 3 tables(FIPLD_VAT_I, FIPLD_VAT_H, and FIPLD_VA_SUM) generated by the note and fulfilled by the report RPFIPL_SAFT with extraction). The idea is that on the official website with legal requirement we received a schema for JPK_VAT and it's XSD format. I need somehow to upload that schema into sap and fulfill it with data from those tables and export in XML.
      Thanks in advance,

      Vlad

       

      Author's profile photo Goran Panic
      Goran Panic

      Hi Kirill,

      Could you please share complete code related to this report?

      Kind regards,

      Goran

      Author's profile photo Valter Miranda
      Valter Miranda

      Hello everyone,

      As Kirill, I have the same situation, that is, no SAP PI, no SOAMANAGER.

      I have the XSD file and if I understood corretly, the program mentioned generate DDIC from XDS file.

      The Kirill text say about the dummy WSDL(is created automatically). I folow all the steps but, after execute de program I receive the message: --> Invalid URL xmldsig-core-schema.xsd <-- In XSD file line 3 (below) there is a call to a schemaLocation="./xmldsig-core-schema.xsd"/. This file is stored at the same directory.

      I am not sure, but in debug mode I saw some access to Kernel Method to obtain the URL. My intention is not  involve basis, but only create a DDIC with all structure table thru a ABAP program.

      Does anyone achieved sucess in this hard work.

      Thanks in advance.

       

      Below, the tiny file XSD to generate DDIC in SAP.

      <?xml version="1.0" encoding="utf-8"?>
      <xs:schema xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://www.reinf.esocial.gov.br/schemas/evtInfoContribuinte/v1_03_00" targetNamespace="http://www.reinf.esocial.gov.br/schemas/evtInfoContribuinte/v1_03_00" elementFormDefault="qualified" attributeFormDefault="unqualified">
        <xs:import namespace="http://www.w3.org/2000/09/xmldsig#" schemaLocation="./xmldsig-core-schema.xsd"/>
        <xs:element name="Reinf">
          <xs:annotation>
            <xs:documentation>EFD-Reinf</xs:documentation>
          </xs:annotation>
          <xs:complexType>
            <xs:sequence>

       

      Valter.

      Author's profile photo Former Member
      Former Member

      Hello all, first, thanks Kirill for your code! I imported this code and added the missing portions from other SAP standard code, here it is, use at own risk. For me it generated quite a number of DDIC structures from the XSD we have received. I have yet to see if it created all the ones needed. Use $TMP package initially to not impact an existing package or dev class. Also for me it did not save on transport probably because I used $TMP initially, and also got a proxy generation error. But it appears the proxy itself can be removed and not transported if needed.

      *&---------------------------------------------------------------------*
      *& report z_import_xml_schema
      *&
      *&---------------------------------------------------------------------*
      *& this reports imports an xsd file and calls standard abap/4 proxy generation
      *& methods to (re-)create ddic objects
      *&---------------------------------------------------------------------*

      REPORT z_import_xml_schema.

      TYPE-POOLS: sprx,
      trwbo.
      CONSTANTS:
      gc_lcl TYPE packname VALUE '$TMP'.
      DATA:
      go_proxy TYPE REF TO cl_proxy,
      gv_xcontent TYPE xstring,
      gv_wsdl TYPE xstring.

      PARAMETERS:
      p_xsdfn TYPE anyuri OBLIGATORY VALUE CHECK. "XML Schema file name

      SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME TITLE text-001.
      PARAMETERS:
      p_pckg TYPE packname VALUE CHECK DEFAULT gc_lcl, " Package
      p_trrq TYPE trkorr VALUE CHECK, " Transport request
      p_prfx TYPE prx_prefix OBLIGATORY DEFAULT 'Z', " Prefix
      p_actv AS CHECKBOX DEFAULT 'X'. " Activate immediately
      SELECTION-SCREEN END OF BLOCK b1.

      * Create Transport request selection dialogue:
      AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_trrq.
      PERFORM get_transport_request CHANGING p_trrq.

      * File name selection dialogue:
      AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_xsdfn.
      PERFORM get_file_name CHANGING p_xsdfn.

      START-OF-SELECTION.

      PERFORM upload_file USING p_xsdfn
      CHANGING gv_xcontent.

      PERFORM xsd2wsdl USING gv_xcontent
      CHANGING gv_wsdl.

      PERFORM init_proxy USING gv_wsdl
      p_pckg
      p_prfx
      CHANGING go_proxy.

      PERFORM save_proxy USING go_proxy.

      IF NOT p_actv IS INITIAL.
      PERFORM activate_proxy USING go_proxy
      p_trrq.
      ENDIF.

      END-OF-SELECTION.

      *&---------------------------------------------------------------------*
      *& Form upload_file
      *&---------------------------------------------------------------------*
      * text
      *----------------------------------------------------------------------*
      * -->IV_FILENAME text
      * -->CV_XCONTENT text
      *----------------------------------------------------------------------*
      FORM upload_file USING iv_filename TYPE anyuri
      CHANGING cv_xcontent TYPE xstring.
      DATA: lo_slib_retriever TYPE REF TO if_slib_retriever,
      lo_exception TYPE REF TO cx_root,
      lv_fault TYPE xstring.

      TRY.
      lo_slib_retriever = cl_slib_entity_container=>create_retriever( ).
      cv_xcontent = lo_slib_retriever->get_content( iv_filename ).
      CATCH cx_slib INTO lo_exception.
      PERFORM output_message USING 'E'
      'Unable to read the file specified.'(urf).
      STOP.
      ENDTRY.
      ENDFORM. "upload_file

      *&---------------------------------------------------------------------*
      *& Form xsd2wsdl
      *&---------------------------------------------------------------------*
      * text
      *----------------------------------------------------------------------*
      * -->IV_XCONTENT text
      * -->CV_WSDL text
      *----------------------------------------------------------------------*
      FORM xsd2wsdl USING iv_xcontent TYPE xstring
      CHANGING cv_wsdl TYPE xstring.

      DATA:
      lv_message TYPE string,
      lx_gen_error TYPE REF TO cx_proxy_gen_error.

      TRY.
      CALL METHOD cl_proxy_test_utils=>xsd2wsdl
      EXPORTING
      schema = iv_xcontent
      RECEIVING
      wsdl = cv_wsdl.
      CATCH cx_proxy_gen_error INTO lx_gen_error .
      lv_message = lx_gen_error->if_message~get_text( ).
      PERFORM output_message USING 'E'
      lv_message.
      STOP.
      ENDTRY.

      ENDFORM. "xsd2wsdl

      *&---------------------------------------------------------------------*
      *& Form init_proxy
      *&---------------------------------------------------------------------*
      * text
      *----------------------------------------------------------------------*
      * -->IV_WSDL text
      * -->IV_PCKG text
      * -->IV_PRAEFIX text
      * -->CO_PROXY text
      *----------------------------------------------------------------------*
      FORM init_proxy USING iv_wsdl TYPE xstring
      iv_pckg
      iv_praefix
      CHANGING co_proxy TYPE REF TO cl_proxy.

      DATA:
      lx_root TYPE REF TO cx_root,
      lv_message TYPE string.

      TRY.
      CALL METHOD cl_proxy_test_utils=>wsdl2proxy
      EXPORTING
      wsdl = iv_wsdl
      package = iv_pckg
      praefix = iv_praefix
      RECEIVING
      proxy = co_proxy.
      CATCH cx_proxy_gen_error INTO lx_root.
      " LX_ROOT is checked below
      CATCH cx_slib INTO lx_root.
      " LX_ROOT is checked below
      CATCH cx_sidl INTO lx_root.
      " LX_ROOT is checked below
      ENDTRY.

      IF lx_root IS BOUND.
      lv_message = lx_root->if_message~get_text( ).
      PERFORM output_message USING 'E'
      lv_message.
      STOP.
      ENDIF.

      ENDFORM. "init_proxy

      *&---------------------------------------------------------------------*
      *& Form save_proxy
      *&---------------------------------------------------------------------*
      * text
      *----------------------------------------------------------------------*
      * -->IO_PROXY text
      *----------------------------------------------------------------------*
      FORM save_proxy USING io_proxy TYPE REF TO cl_proxy.
      DATA:
      lx_error TYPE REF TO cx_proxy_gen_error,
      lv_message TYPE string.

      TRY.
      CALL METHOD io_proxy->save
      CHANGING
      transport_number = p_trrq.
      CATCH cx_proxy_gen_error INTO lx_error .

      lv_message = lx_error->if_message~get_text( ).
      PERFORM output_message USING 'E'
      lv_message.
      STOP.

      ENDTRY.

      " No errors:
      PERFORM output_message USING 'S'
      'Proxy was saved.'(pws).

      ENDFORM. "save_proxy

      *&---------------------------------------------------------------------*
      *& Form activate_proxy
      *&---------------------------------------------------------------------*
      * text
      *----------------------------------------------------------------------*
      * -->IO_PROXY text
      * -->IV_TRREQ text
      *----------------------------------------------------------------------*
      FORM activate_proxy USING io_proxy TYPE REF TO cl_proxy
      iv_trreq TYPE trkorr .
      DATA:
      lt_objects TYPE sprx_log_t,
      lt_log TYPE sprx_log_t,
      ls_objects LIKE LINE OF lt_objects,
      ls_log LIKE LINE OF lt_log,
      lx_error TYPE REF TO cx_proxy_gen_error,
      lv_message TYPE string.

      TRY.
      CALL METHOD io_proxy->activate
      EXPORTING
      activate_all = 'X'
      deletion = 'X'
      IMPORTING
      activated_objects = lt_objects
      log = lt_log
      CHANGING
      transport_number = iv_trreq.
      CATCH cx_proxy_gen_error INTO lx_error.
      lv_message = lx_error->if_message~get_text( ).
      PERFORM output_message USING 'E'
      lv_message.
      STOP.
      ENDTRY.

      IF NOT lt_log[] IS INITIAL.
      PERFORM output_message USING 'I'
      'Activation log:'(alo).
      LOOP AT lt_log INTO ls_log.

      MESSAGE ID ls_log-msgid
      TYPE ls_log-msgty
      NUMBER ls_log-msgno
      WITH ls_log-msgv1
      ls_log-msgv2
      ls_log-msgv3
      ls_log-msgv4
      INTO lv_message.
      PERFORM output_message USING ls_log-msgty
      lv_message.
      ENDLOOP.
      ENDIF.

      IF NOT lt_objects[] IS INITIAL.
      PERFORM output_message USING 'I'
      'Activated objects:'(oli).
      LOOP AT lt_objects INTO ls_objects.

      MESSAGE ID ls_objects-msgid
      TYPE ls_objects-msgty
      NUMBER ls_objects-msgno
      WITH ls_objects-msgv1
      ls_objects-msgv2
      ls_objects-msgv3
      ls_objects-msgv4
      INTO lv_message.
      PERFORM output_message USING ls_objects-msgty
      lv_message.
      ENDLOOP.
      ENDIF.
      ENDFORM. "activate_proxy
      *&---------------------------------------------------------------------*
      *& Form OUTPUT_MESSAGE
      *&---------------------------------------------------------------------*
      * text
      *----------------------------------------------------------------------*
      * -->P_0116 text
      * -->P_0117 text
      *----------------------------------------------------------------------*
      FORM output_message USING i_msg
      i_text.
      WRITE : / i_msg, i_text.

      ENDFORM. " OUTPUT_MESSAGE
      *&---------------------------------------------------------------------*
      *& Form GET_FILE_NAME
      *&---------------------------------------------------------------------*
      * text
      *----------------------------------------------------------------------*
      * <--P_P_XSDFN text
      *----------------------------------------------------------------------*
      FORM get_file_name CHANGING filename.

      DATA:
      l_rc TYPE i,
      l_action TYPE i,
      l_file_table TYPE filetable,
      l_file TYPE LINE OF filetable,
      l_title TYPE string.

      l_title = 'File name'(001).

      CALL METHOD cl_gui_frontend_services=>file_open_dialog
      EXPORTING
      window_title = l_title
      multiselection = space
      CHANGING
      file_table = l_file_table
      rc = l_rc
      user_action = l_action
      EXCEPTIONS
      file_open_dialog_failed = 1
      cntl_error = 2
      error_no_gui = 3
      not_supported_by_gui = 4
      OTHERS = 5.

      IF sy-subrc = 0 AND l_rc = 1 AND l_action = cl_gui_frontend_services=>action_ok.
      READ TABLE l_file_table INDEX 1 INTO l_file.
      filename = l_file-filename.
      ENDIF.

      ENDFORM. " GET_FILE_NAME
      *&---------------------------------------------------------------------*
      *& Form GET_TRANSPORT_REQUEST
      *&---------------------------------------------------------------------*
      * text
      *----------------------------------------------------------------------*
      * <--transport text
      *----------------------------------------------------------------------*
      FORM get_transport_request CHANGING transport.

      DATA: lv_len TYPE n,
      lv_trfunction LIKE e070-trfunction,
      ls_user TYPE trwbo_user,
      lt_users TYPE trwbo_users,
      ls_new_request TYPE trwbo_request_header.

      CALL FUNCTION 'TR_POPUP_SELECT_REQUEST_TYPE'
      EXPORTING
      iv_trfunctions = 'KWTCEO' "all transport types
      iv_title = 'Create transport'
      IMPORTING
      ev_trfunction = lv_trfunction
      EXCEPTIONS
      action_aborted_by_user = 1.
      IF sy-subrc <> 0.
      PERFORM send_current_message USING 'S'.
      EXIT.
      ENDIF.

      IF lv_trfunction CA 'KW'.
      ls_user-user = sy-uname.
      APPEND ls_user TO lt_users.
      ENDIF.

      CALL FUNCTION 'TR_REQUEST_MODIFY'
      EXPORTING
      iv_action = 'CREA'
      iv_new_request_type = lv_trfunction
      it_users = lt_users
      IMPORTING
      es_new_request = ls_new_request
      EXCEPTIONS
      OTHERS = 1.
      IF sy-subrc <> 0.
      PERFORM send_current_message USING 'S'.
      EXIT.
      ENDIF.

      transport = ls_new_request-trkorr.

      CALL FUNCTION 'TR_PRESENT_REQUEST'
      EXPORTING
      iv_trkorr = ls_new_request-trkorr.

      ENDFORM. " GET_TRANSPORT_REQUEST
      *&---------------------------------------------------------------------*
      *& Form SEND_CURRENT_MESSAGE
      *&---------------------------------------------------------------------*
      * text
      *----------------------------------------------------------------------*
      * -->pv_mstyp text
      *----------------------------------------------------------------------*
      FORM send_current_message USING value(pv_mstyp) LIKE sy-msgty.
      MESSAGE ID sy-msgid
      TYPE pv_mstyp
      NUMBER sy-msgno
      WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
      ENDFORM. " SEND_CURRENT_MESSAGE