Posted: Fri Oct 26, 2007 5:23 pm Post subject: Convert a XML file into an ABAP table using SAP DOM Approach
XML DOM Processing in ABAP part II - Convert an XML file into an ABAP table using SAP DOM Approach.
Robert Eijpe
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.
Next we will parse the stream to a XML DOM object using a using an iXML factory.
And finally we have a XML DOM Object and we can access its nodes to fill our table.
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.
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.
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.
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.
TYPES: BEGIN OF t_xml_line,
data(256) TYPE x,
END OF t_xml_line.
DATA: l_ixml TYPE REF TO if_ixml,
l_streamfactory TYPE REF TO if_ixml_stream_factory,
l_parser TYPE REF TO if_ixml_parser,
l_istream TYPE REF TO if_ixml_istream,
l_document TYPE REF TO if_ixml_document,
l_node TYPE REF TO if_ixml_node,
l_xmldata TYPE string.
DATA: l_elem TYPE REF TO if_ixml_element,
l_root_node TYPE REF TO if_ixml_node,
l_next_node TYPE REF TO if_ixml_node,
l_name TYPE string,
l_iterator TYPE REF TO if_ixml_node_iterator.
DATA: l_xml_table TYPE TABLE OF t_xml_line,
l_xml_line TYPE t_xml_line,
l_xml_table_size TYPE i.
DATA: l_filename TYPE string.
PARAMETERS: pa_file TYPE char1024 DEFAULT 'c:\temp\orders_dtd.xml'.
* Validation of XML file: Only DTD included in xml document is supported
PARAMETERS: pa_val TYPE char1 AS CHECKBOX.
START-OF-SELECTION.
* Creating the main iXML factory
l_ixml = cl_ixml=>create( ).
* Creating a stream factory
l_streamfactory = l_ixml->create_stream_factory( ).
* Validate a document
IF pa_val EQ 'X'.
l_parser->set_validating( mode = if_ixml_parser=>co_validate ).
ENDIF.
* Parse the stream
IF l_parser->parse( ) NE 0.
IF l_parser->num_errors( ) NE 0.
DATA: parseerror TYPE REF TO if_ixml_parse_error,
str TYPE string,
i TYPE i,
count TYPE i,
index TYPE i.
count = l_parser->num_errors( ).
WRITE: count, ' parse errors have occured:'.
index = 0.
WHILE index <count>get_error( index = index ).
i = parseerror->get_line( ).
WRITE: 'line: ', i.
i = parseerror->get_column( ).
WRITE: 'column: ', i.
str = parseerror->get_reason( ).
WRITE: str.
index = index + 1.
ENDWHILE.
ENDIF.
ENDIF.
* Process the document
IF l_parser->is_dom_generating( ) EQ 'X'.
PERFORM process_dom USING l_document.
ENDIF.
*&--------------------------------------------------------------------*
*& Form get_xml_table
*&--------------------------------------------------------------------*
FORM get_xml_table CHANGING l_xml_table_size TYPE i
l_xml_table TYPE STANDARD TABLE.
* Local variable declaration
DATA: l_len TYPE i,
l_len2 TYPE i,
l_tab TYPE tsfixml,
l_content TYPE string,
l_str1 TYPE string,
c_conv TYPE REF TO cl_abap_conv_in_ce,
l_itab TYPE TABLE OF string.
l_filename = pa_file.
* upload a file from the client's workstation
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 = 19.
IF sy-subrc <0>create( input = l_xml_line-data replacement = space ).
c_conv->read( IMPORTING data = l_content len = l_len ).
CONCATENATE l_str1 l_content INTO l_str1.
ENDLOOP.
l_str1 = l_str1+0(l_xml_table_size).
SPLIT l_str1 AT cl_abap_char_utilities=>cr_lf INTO TABLE l_itab.
WRITE: /.
WRITE: /' XML File'.
WRITE: /.
LOOP AT l_itab INTO l_str1.
REPLACE ALL OCCURRENCES OF cl_abap_char_utilities=>horizontal_tab IN
l_str1 WITH space.
WRITE: / l_str1.
ENDLOOP.
WRITE: /.
ENDFORM. "get_xml_table
*&--------------------------------------------------------------------*
*& Form process_dom
*&--------------------------------------------------------------------*
FORM process_dom USING document TYPE REF TO if_ixml_document.
DATA: node TYPE REF TO if_ixml_node,
iterator TYPE REF TO if_ixml_node_iterator,
nodemap TYPE REF TO if_ixml_named_node_map,
attr TYPE REF TO if_ixml_node,
name TYPE string,
prefix TYPE string,
value TYPE string,
indent TYPE i,
count TYPE i,
index TYPE i.
node ?= document.
CHECK NOT node IS INITIAL.
ULINE.
WRITE: /.
WRITE: /' DOM-TREE'.
WRITE: /.
IF node IS INITIAL. EXIT. ENDIF.
* create a node iterator
iterator = node->create_iterator( ).
* get current node
node = iterator->get_next( ).
* loop over all nodes
WHILE NOT node IS INITIAL.
indent = node->get_height( ) * 2.
indent = indent + 20.
CASE node->get_type( ).
WHEN if_ixml_node=>co_node_element.
* element node
name = node->get_name( ).
nodemap = node->get_attributes( ).
WRITE: / 'ELEMENT :'.
WRITE: AT indent name COLOR COL_POSITIVE INVERSE.
IF NOT nodemap IS INITIAL.
* attributes
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( ).
WRITE: / 'ATTRIBUTE:'.
WRITE: AT indent name COLOR COL_HEADING INVERSE, '=',
value COLOR COL_TOTAL INVERSE.
ENDDO.
ENDIF.
WHEN if_ixml_node=>co_node_text OR
if_ixml_node=>co_node_cdata_section.
* text node
value = node->get_value( ).
WRITE: / 'VALUE :'.
WRITE: AT indent value COLOR COL_GROUP INVERSE.
ENDCASE.
* advance to next node
node = iterator->get_next( ).
ENDWHILE.
ENDFORM. "process_dom
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum You cannot attach files in this forum You can download files in this forum
All product names are trademarks of their respective companies. SAPNET.RU websites are in no way affiliated with SAP AG. SAP, SAP R/3, R/3 software, mySAP, ABAP, BAPI, xApps, SAP NetWeaver and any other are registered trademarks of SAP AG. Every effort is made to ensure content integrity. Use information on this site at your own risk.