03-30-2009 11:25 AM
Hi Expert,
I need to write a transformation and convert an XML file into ABAP data.
The XML looks like following:
<?xml version="1.0" ?>
- <ServiceProtocol version="2.1">
- <CmdTest CheckId="123456789">
- <ExceptionMessage>
<id>003</id>
<text>Test</text>
- <arguments>
<argument>2.2</argument>
<argument>2.1</argument>
</arguments>
<creator>Hello</creator>
</ExceptionMessage>
</CmdTest>
</ServiceProtocol>
I have no knowledge in transformation. Can some one help me on this or provide deatail guideline on the conversion of XML to ABAP data.
Thanks in advance,
Best Regards, Johnney.
03-30-2009 7:31 PM
Hi Johnney,
It's actually not that difficult. For that little XML of yours, I would suggest a Simple Transformation, because it's ... simple. And fast.
You should do some reading in the online documentation, and then it's trial-and-error. To accelerate your trialling, I've prepared a little example for you. Which you can use as follows.
Call SE80, and go Workbench > Edit object... , and create a "Transformation" (you give it a suitable name, and click on the "Create" button; in the pop-up, you specify Transformation type = "Simple transformation").
In the source code, you replace everything between "<tt:transform>" and "</tt:transform>" with the following bit of code:
<tt:root name="PROTOCOL_VERSION"/>
<tt:root name="CHECK_ID"/>
<tt:root name="MESSAGE_ID"/>
<tt:root name="MESSAGE_TEXT"/>
<tt:root name="CREATOR"/>
<tt:root name="T_ARGUMENTS"/>
<tt:template>
<ServiceProtocol>
<tt:attribute name="version" value-ref="PROTOCOL_VERSION"/>
<CmdTest>
<tt:attribute name="CheckId" value-ref="CHECK_ID"/>
<ExceptionMessage>
<id>
<tt:value ref="MESSAGE_ID"/>
</id>
<text>
<tt:value ref="MESSAGE_TEXT"/>
</text>
<arguments>
<tt:loop name="Arguments" ref="T_ARGUMENTS">
<argument>
<tt:value ref="$Arguments.ARGUMENT"/>
</argument>
</tt:loop>
</arguments>
<creator>
<tt:value ref="CREATOR"/>
</creator>
</ExceptionMessage>
</CmdTest>
</ServiceProtocol>
</tt:template>
Your simple transformation is ready; all you have to do is call it from a little program, more or less as follows:
DATA:
l_prot_version TYPE string,
l_check_id TYPE string,
l_msg_id TYPE string,
l_msg_text TYPE string,
l_creator TYPE string,
BEGIN OF ls_arguments,
argument TYPE string,
END OF ls_arguments,
lt_arguments LIKE STANDARD TABLE OF ls_arguments.
TRY.
CALL TRANSFORMATION your_transformation_name
SOURCE XML l_xml_string
RESULT protocol_version = l_prot_version
check_id = l_check_id
message_id = l_msg_id
message_text = l_msg_text
t_arguments = lt_arguments
creator = l_creator.
CATCH cx_st_error.
* Your error handling comes here...
ENDTRY.
The variables starting with "l_" should be character fields of appropriate length, or character strings, while "lt_arguments" should be a standard table with a single field called "ARGUMENT" (otherwise you'd have to change the name in the transformation, in the line that says "<tt:value ref="$Arguments.ARGUMENT"/>").
There's more pitfalls for you, like the encoding of the XML string, but you'll find examples of how to handle that if you look for class CL_ABAP_CONV_IN_CE, either here in the forum or in your system (or in the online help, of course).
Oh, and you should definitely catch and handle CX_ST_ERROR - transformations dump easily if something is wrong with the data.
Hope this helps - sure took longer than planned...
Rainer
03-30-2009 12:03 PM
03-30-2009 7:31 PM
Hi Johnney,
It's actually not that difficult. For that little XML of yours, I would suggest a Simple Transformation, because it's ... simple. And fast.
You should do some reading in the online documentation, and then it's trial-and-error. To accelerate your trialling, I've prepared a little example for you. Which you can use as follows.
Call SE80, and go Workbench > Edit object... , and create a "Transformation" (you give it a suitable name, and click on the "Create" button; in the pop-up, you specify Transformation type = "Simple transformation").
In the source code, you replace everything between "<tt:transform>" and "</tt:transform>" with the following bit of code:
<tt:root name="PROTOCOL_VERSION"/>
<tt:root name="CHECK_ID"/>
<tt:root name="MESSAGE_ID"/>
<tt:root name="MESSAGE_TEXT"/>
<tt:root name="CREATOR"/>
<tt:root name="T_ARGUMENTS"/>
<tt:template>
<ServiceProtocol>
<tt:attribute name="version" value-ref="PROTOCOL_VERSION"/>
<CmdTest>
<tt:attribute name="CheckId" value-ref="CHECK_ID"/>
<ExceptionMessage>
<id>
<tt:value ref="MESSAGE_ID"/>
</id>
<text>
<tt:value ref="MESSAGE_TEXT"/>
</text>
<arguments>
<tt:loop name="Arguments" ref="T_ARGUMENTS">
<argument>
<tt:value ref="$Arguments.ARGUMENT"/>
</argument>
</tt:loop>
</arguments>
<creator>
<tt:value ref="CREATOR"/>
</creator>
</ExceptionMessage>
</CmdTest>
</ServiceProtocol>
</tt:template>
Your simple transformation is ready; all you have to do is call it from a little program, more or less as follows:
DATA:
l_prot_version TYPE string,
l_check_id TYPE string,
l_msg_id TYPE string,
l_msg_text TYPE string,
l_creator TYPE string,
BEGIN OF ls_arguments,
argument TYPE string,
END OF ls_arguments,
lt_arguments LIKE STANDARD TABLE OF ls_arguments.
TRY.
CALL TRANSFORMATION your_transformation_name
SOURCE XML l_xml_string
RESULT protocol_version = l_prot_version
check_id = l_check_id
message_id = l_msg_id
message_text = l_msg_text
t_arguments = lt_arguments
creator = l_creator.
CATCH cx_st_error.
* Your error handling comes here...
ENDTRY.
The variables starting with "l_" should be character fields of appropriate length, or character strings, while "lt_arguments" should be a standard table with a single field called "ARGUMENT" (otherwise you'd have to change the name in the transformation, in the line that says "<tt:value ref="$Arguments.ARGUMENT"/>").
There's more pitfalls for you, like the encoding of the XML string, but you'll find examples of how to handle that if you look for class CL_ABAP_CONV_IN_CE, either here in the forum or in your system (or in the online help, of course).
Oh, and you should definitely catch and handle CX_ST_ERROR - transformations dump easily if something is wrong with the data.
Hope this helps - sure took longer than planned...
Rainer
02-14-2011 9:13 PM
Hello Rainer,
I was following your blog (the most usefull) of any XML post I have seen on SDN and ran into problem definition of data types: abap_trans_resbind_tab, abap_trans_resbind do not exist in our system. What definition can use instead ?
Your Forum was very helpfull.
Thank You in advance.
Ken
06-15-2009 11:15 AM
<pre>
DATA itab_accontextdir TYPE TABLE OF ACCONTEXTDIR.
DATA struct_accontextdir LIKE LINE OF itab_accontextdir.
DATA l_o_error TYPE REF TO cx_root.
DATA: filename type string ,
xmldata type xstring .
DATA: mr TYPE REF TO if_mr_api.
mr = cl_mime_repository_api=>get_api( ).
mr->get( EXPORTING i_url = 'SAP/PUBLIC/BC/xml_files_accontext/xml_accontextdir.xml'
IMPORTING e_content = xmldata ).
WRITE xmldata.
TRY.
CALL TRANSFORMATION id
SOURCE XML xmldata
RESULT shiva = itab_accontextdir.
CATCH cx_root INTO l_o_error.
ENDTRY.
LOOP AT itab_accontextdir INTO struct_accontextdir.
WRITE: / struct_accontextdir-context_id,
struct_accontextdir-context_name,
struct_accontextdir-context_type.
NEW-LINE.
ENDLOOP.
</pre>
<br/>
Description: In the above code snippet I am storing the data in an xml file(you know xml is used to store and transport data ) called 'xml_accontextdir.xml' that is uploaded into the MIME repository at path 'SAP/PUBLIC/BC/xml_files_accontext/xml_accontextdir.xml'. The below API is used to read a file in MIME repo and convert it into a string that is stored in ' xmldata'. (This is just a raw data that is got by appending the each line of xml file). mr = cl_mime_repository_api=>get_api( ). mr->get( EXPORTING i_url = 'SAP/PUBLIC/BC/xml_files_accontext/xml_accontextdir.xml' IMPORTING e_content = xmldata ). Once the 'xmldata' string is available we use the tranformation to parse the xml string that we have got from the above API and convert it into the internal table.
<pre>
TRY.
CALL TRANSFORMATION id
SOURCE XML xmldata
RESULT shiva = itab_accontextdir.
CATCH cx_root INTO l_o_error.
ENDTRY.
</pre>
</br>
Here the trasnsformation 'id ' is used to conververt the source xml 'xmldata' to resulting internal table itab_accontextdir, that have same structure as our xml file 'xml_accontextdir.xml'. In the RESULT root of the xml file has to be specified. (In my the root is 'shiva'). Things to be taken care: One of the major problem that occurs when reading the xml file is 'format not compatible with the internal table' that you are reading into internal table. Iin order to get rid of this issue use one more tranformation to convert the data from the internal table into the xml file.
</br>
<pre>
TRY.
CALL TRANSFORMATION id
SOURCE shiv = t_internal_tab
RESULT XML xml.
CATCH cx_root INTO l_o_error.
ENDTRY.
WRITE xml.
NEW-LINE.
</pre>
This is the same transformation that we used above but the differnce is that the SOURCE and RESULT parameters are changed the source is now the internal table and result is *xml *string. Use xml browser that is available with the ABAP workbench to read the xml string displayed with proper indentation. In this way we get the format of xml file to be used that is compatable with the given internal table. Thank you, Hope this will help you!!!
08-17-2009 12:36 PM
xml browser that is available with the ABAP workbench to read the xml string displayed with proper indentation.
i wonder where to find xml browser in abap workbench..
can anyone help me with that.
08-17-2009 12:44 PM
07-10-2012 5:49 AM
Hi,
Call transfomation is not working for me. I am getting exception "CX_MATCH_ELEMENT".
My XML data will be like:
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
</data>
Using some methods i am able to fetch this data into a string abap variable. how can i parse this data & store it to required format/ to a internal table?
Thanks,
Arvind