Skip to Content

Introduction

In this weblog I will focus on the possibilities of SAP XML Document Object Model (DOM) processing at the ABAP stack. My objective is to explain how you can use it in abap mapping. For this I split this weblog into three parts. This document is the second-in-the-series and will focus on the conversion from a XML file (back) to an ABAP table. This first part focused on the conversion of an ABAP table into an XML file and the last part will deal with the use of SAP DOM within XI ABAP mapping, introduced with SAP XI 3.0.

The XML

In this weblog we will focus on retrieving data from a local XML file and store it in an internal table.
We will start with an upload of a local XML file into a binary XML table and we will bind it to a XML input stream.
image

Next we will parse the stream to a XML DOM object using a using an iXML factory.
image

And finally we have a XML DOM Object and we can access its nodes to fill our table.
image

The implementation

In the implementation we will explain the steps of the process and at the end of the log you will find a complete source sample.
To upload the XML file, you need the filename and you have to declare an internal binary table to store the uploaded XML file.

  TYPES: t_xml_line(1024) TYPE x.
 
  DATA: l_filename        TYPE string,
        l_xml_table       TYPE TABLE OF t_xml_line,
        l_xml_line        TYPE t_xml_line,
        l_xml_table_size  TYPE i.
        

    CALL METHOD cl_gui_frontend_services=>gui_upload
      EXPORTING
        filename   = l_filename
        filetype   = ‘BIN’
      IMPORTING
        filelength = l_xml_table_size
      CHANGING
        data_tab   = l_xml_table
      EXCEPTIONS
        OTHERS     = 1.
    IF sy-subrc <> 0.
      MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
                 WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
    ENDIF.

When you have the XML file in a binary table, you can start to process the XML data. To do this we need an iXML factory which will help us create an input stream from the binary table.  

 TYPE-POOLS: ixml.
 DATA: l_ixml TYPE REF TO if_ixml.
 l_ixml = cl_ixml=>create( ).


This iXML factory can create a XML stream factory which actually creates an input stream based on the binary table.

 DATA: l_streamfactory   TYPE REF TO if_ixml_stream_factory,
       l_istream         TYPE REF TO if_ixml_istream.

 l_streamfactory = l_ixml->create_stream_factory( ).

 l_istream = l_streamfactory->create_istream_itable(
                                table = l_xml_table
                                size  = l_xml_table_size ).


Before creating the XML DOM object you have to create an empty document and a parser object. The document object will represent the DOM object and the parser is needed to convert the XML stream into a XML DOM object.

 DATA:  l_document TYPE REF TO if_ixml_document,
         l_parser    TYPE REF TO if_ixml_parser.

 l_document = l_ixml->create_document( ).
 l_parser = l_ixml->create_parser(
                      stream_factory = l_streamfactory
                      istream        = l_istream
                      document       = l_document ).


After having created the parser, the empty document and the input stream, you can start the conversion using the parse method of the parser. If the parsing failes, you  can retrieve the error using the if_xml_parse_error interface.

 DATA: l_parse_error TYPE REF TO if_ixml_parse_error.

 IF l_parser->parse( ) NE 0.
  IF l_parser->num_errors( ) NE 0.
   …
   l_parse_error = l_parser->get_error( index = l_index ).
   …
  ENDIF.
 ENDIF.

At this point you have to check if the DOM was really created and if so you can process the document.

 IF l_parser->is_dom_generating( ) EQ ‘X’.
  PERFORM process_dom USING l_document.
 ENDIF.

To process it you need to cast the document to a node interface object.

 DATA: node      TYPE REF TO if_ixml_node,
       iterator  TYPE REF TO if_ixml_node_iterator.

 node ?= document.

 CHECK NOT node IS INITIAL.

When having the DOM object as a node object, you can use an iterator to “walk” trough the DOM object. To do this you have to create the iterator of the node object and get the root node using the get_next method of the iterator.

 iterator  = node->create_iterator( ).
 node = iterator->get_next( ).

Scrolling through the DOM, you can fill your internal table. The method get_type will tell you if the node is an element- of a text node.  In the element node you will find the name of the element and the attribute which belong to the element node. In the text node, you will find the value of the element node.

 WHILE NOT node IS INITIAL.
  CASE node->get_type( ).
   WHEN if_ixml_node=>co_node_element.
    name  = node->get_name( ).
    …
   WHEN if_ixml_node=>co_node_text OR
        if_ixml_node=>co_node_cdata_section.
    value = node->get_value( ).
    …
  ENDCASE.
  node = iterator->get_next( ).
 ENDWHILE.

The attributes of an element will be available in a node map with the interface if_ixml_named_node_map. This interface can be used to read the names and values of the attributes in the element.

 nodemap = node->get_attributes( ).
 IF NOT nodemap IS INITIAL.
  count = nodemap->get_length( ).
  DO count TIMES.
   index  = sy-index – 1.
   attr   = nodemap->get_item( index ).
   name   = attr->get_name( ).
   prefix = attr->get_namespace_prefix( ).
   value  = attr->get_value( ).
   …
  ENDDO.
 ENDIF.

This finished the second step-of-three. As mentioned before the next log will focus on the use of SAP DOM within XI ABAP mapping.

A complete example

To report this post you need to login first.

24 Comments

You must be Logged on to comment or reply to a post.

  1. HI Robert,

    I have been using SAP DOM for parsing in ABAP mapping. Initially i had a hard time with figuring out the SAP DOM implementation of DOM iteraters.

    Your weblog gives a very good insight into how to use the iterator for walking through the DOM.

    Cheers,
    Naveen

    (0) 
  2. Tobias Trapp
    Hi Robert,

    I didn’t check it under every release but in my opinion you don’t need to perform following check:

      IF l_parser->is_dom_generating( ) EQ ‘X’.
        PERFORM process_dom USING l_document.
      ENDIF.

    If you call the method parse() the methods set_dom_generating() and is_dom_generating() have no effect. Only if you parse SAX-like by calling parseEvent() you can choose whether a complete DOM-tree should be generated or only the path to the root during event processing.

    Keep on blogging!

    Cheers,
    Tobias

    (0) 
  3. Maria João Paulo Rocha
    Thanks for the article.
    I’ve run the example under 6.20 and it worked fine, but not with 4.6c!

    The method set_validating doesn’t exist on 4.6c. Is there another solution for this task?

    Best Regards,
    Maria João Rocha

    (0) 
    1. Tobias Trapp
      Sorry, but validating isn’t possible in 4.6C.

      If you work with XML-Libary in 4.6C I suggest to watch at OSS-patches because on a low patch level some problems may ocurr.

      Cheers,
      Tobias

      (0) 
  4. Community User
    Hi Robert

    Both parts 1 & 2 have been very useful in explaining  the conversion to and from an XML structure.

    When do you anticipate part 3 will be available?

    Many thanks.
    Daniel

    (0) 
  5. sudha jupudi
    Hi,
    Your artical is really a great help for the beginners like me.Presently i got a requirement to conver the idoc data into xml file and the xml to idoc from application server. can you please giude me if you have any tips.

    Thanks in advance,
    Sudha Jupudi

    (0) 
  6. Sten Kristian Finckenhagen
    Dear Robert,

    Thanks a lot for your effort. It is much appreciated!

    In your coding example you’ve stated that the DTD needs to be part of the XML file (Validation of XML file: Only DTD included in xml document is supported).

    I’ve got an XML file and a corresponding DTD which I’ve tried to incorporate to no avail.

    Could you please post a very brief example file which indicates how the DTD is to be included in the XML file?

    Thanks a lot!

    Kind regards,

    Sten

    (0) 
  7. Russell Smith
    This blog has realy helped me with my current project which, in phase one, writes xml files at order save and delivery save times to an external server.  In phase two I need to read an xml file that is returned to me from a vendor and convert it into an internal table for processing.  My problem is that I need to get the xml file in the background.  In your example you use a call to the method cl_gui_frontend_services=>gui_upload to get the file which fails when called by our edi subsystem.  I am attempting to use open dataset to get the file but I am running into many problems with my parser object.  Can you offer any suggestions on how to get the xml properly in the background?

    Thanks,

    Russ

    (0) 
  8. Sreekanth Gollamudi
    During the migration process problems have been reported for this blog. The blog content may look corrupt due to not supported HTML code on this platform. Please adjust the blog content manually before moving it to an official community.
    (0) 
  9. Premal Mistry
    Hi,

    I have a scenario in which I am receiving a WSDL file through EDI. Now that WSDL file contains two parts i.e. One containing Data Security part and Other is my actual data part.

    Now my concern is with the actual data. I need to get the data from that WSDL file into internal table and from there into the database table.

    I needed to know whether there is any sort of adapters or class through which i could convert the WSDL file into the XML file and from there I can read that XMl file into the internal table.

    (0) 
  10. jessica sam
    I have a requirement. I need to convert an XML file to internal table data and based on that data do Goods Receipt in SAP.

    With the help of this blog XML DOM Processing in ABAP part I –  Convert an ABAP table into XML file using SAP DOM Approach.
    I am able to convert the XML file to data in SAP. But this blog will display the output on screen as ELELEMNT = nodename VALUE= value of that node.

    But I don’t want in that way, I want to store all the data in XML file in an internal table so that I can make use of those values and do Goods Recipt in SAP.
    Can some one suggest how should I read the data in an internal table.
    what changes should I make?

    (0) 
  11. Roberto Baldassarre
    Hello,

    I tried to execute this exemple but I got the follow DUMP:

    LOOP AT l_xml_table INTO l_xml_line.
    c_conv = cl_abap_conv_in_ce=>create( input = l_xml_line-data replacement = space ).
    c_conv->read( IMPORTING data = l_content len = l_len ).

    (dump)CONCATENATE l_str1 l_content INTO l_str1.
    ENDLOOP.

    dump description:

    Erreur d’exécution CONVT_CODEPAGE
    Exception CX_SY_CONVERSION_CODEPAGE
    Date et heure 29.04.2009 11:50:38

    Désignation
    A character set conversion is not possible.

    Causes
    At the conversion of a text from codepage ‘4110’ to codepage ‘4103’:

    – a character was found that cannot be displayed in one of the two
    codepages;
    – or it was detected that this conversion is not supported

    The running ABAP program ‘CL_ABAP_CONV_IN_CE============CP’ had to be
    terminated as the conversion
    would have produced incorrect data.

    The number of characters that could not be displayed (and therefore not
    be converted), is 1. If this number is 0, the second error case, as
    mentioned above, has occurred.

    Any idea ?
    Tks.

    (0) 
  12. Kumar Manikonda
    Hi,

    I have a requirement, i will receive a XML file from non-sap for inbound interface ,Please let me know is there any solution for this, and currenly i am working with LSMW IDOC method,

    can you give me any sollution for this issue.

    regards,

    Kumar M

    (0) 

Leave a Reply