Application Development and Automation Discussions
Join the discussions or start your own on all things application development, including tools and APIs, programming models, and keeping your skills sharp.
cancel
Showing results for 
Search instead for 
Did you mean: 
Read only

Converting XML into ABAP

Former Member
0 Likes
5,137

Hi guys!

I have a problem. I want to have data from a simple XML-File into an ABAP-itab.

This is the XML file:

<?xml version="1.0" encoding="UTF-16"?>

<F>

<P1>

<t_1>value1</t_1>

<t_2>testvalue</t_2>

</P1>

<P2>

</P2>

</F>

I made a XSLT-Program, but it must have an error:

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

<xsl:strip-space elements="*"/>

<xsl:template match="F">

<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">

<asx:values>

<DOCUMENT>

<xsl:apply-templates/>

</DOCUMENT>

</asx:values>

</asx:abap>

</xsl:template>

<xsl:template match="P1">

<t_1><xsl:value-of select="t_1"/></t_1>

<t_2><xsl:value-of select="t_2"/></t_2>

</xsl:template>

</xsl:transform>

My ABAP-Report looks like this:

DATA: BEGIN OF wa_upload,

text(255) TYPE c,

END OF wa_upload,

itab_upload LIKE TABLE OF wa_upload,

BEGIN OF wa_document,

t_1 TYPE string,

t_2 TYPE string,

END OF wa_document,

itab_document LIKE TABLE OF wa_document.

CALL FUNCTION 'GUI_UPLOAD'

EXPORTING

filename = 'C:\test.xml'

filetype = 'ASC'

TABLES

data_tab = itab_upload.

CALL TRANSFORMATION zrappel_xml_test

SOURCE XML itab_upload

RESULT document = itab_document.

Executing this report i alway get a CX_XSLT_RUNTIME_ERROR with Exception ' '. (Yes, exception is blank )

Can anyone see the failure?

Greetings

Roland

1 ACCEPTED SOLUTION
Read only

Former Member
0 Likes
4,875

Hi Ronald,

Could you go through the following code for XML to ABAP. I think it helps you a bit.

XML File

-

-


-

-


ABAP Coding

*&----


*

*& Report ZABN_XML_TO_ABAP *

*& *

*&----


*

REPORT ZABN_XML_TO_ABAP .

  • Load iXML Lib.

TYPE-POOLS: IXML.

CLASS CL_IXML DEFINITION LOAD.

DATA: G_IXML TYPE REF TO IF_IXML.

DATA: STREAMFACTORY TYPE REF TO IF_IXML_STREAM_FACTORY.

DATA: ISTREAM TYPE REF TO IF_IXML_ISTREAM.

DATA: DOCUMENT TYPE REF TO IF_IXML_DOCUMENT.

DATA: PARSER TYPE REF TO IF_IXML_PARSER.

DATA: LV_FILE_URL TYPE RLGRAP-FILENAME.

LV_FILE_URL = 'C:input_xml.xml'.

TYPES: BEGIN OF XML_LINE,

DATA(256) TYPE X,

END OF XML_LINE.

TYPES: BEGIN OF TY_HEADER,

CUST_NAME(20) TYPE C,

CARD_NO(20) TYPE C,

TAX_AMOUNT(10) TYPE C,

TOTAL_AMOUNT(10) TYPE C,

END OF TY_HEADER.

TYPES: BEGIN OF TY_ITEM,

ITEM_NO(4) TYPE N,

ITEM_ID(20) TYPE C,

ITEM_TITLE(50) TYPE C,

ITEM_QTY(10) TYPE C,

ITEM_UPRICE(10) TYPE C,

END OF TY_ITEM.

DATA: GV_HEADER TYPE TY_HEADER.

DATA: GT_ITEM TYPE STANDARD TABLE OF TY_ITEM WITH HEADER LINE.

DATA: XML_TABLE TYPE TABLE OF XML_LINE,

XML_TABLE_SIZE TYPE I.

  • The next step is creating the main factory for the iXML library:

G_IXML = CL_IXML=>CREATE( ).

  • Now Create Stream Factory

STREAMFACTORY = G_IXML->CREATE_STREAM_FACTORY( ).

  • upload a file from the client's workstation

CALL FUNCTION 'WS_UPLOAD'

EXPORTING

FILENAME = LV_FILE_URL

FILETYPE = 'BIN'

IMPORTING

FILELENGTH = XML_TABLE_SIZE

TABLES

DATA_TAB = XML_TABLE

EXCEPTIONS

OTHERS = 11.

  • wrap the table containing the file into a stream

ISTREAM = STREAMFACTORY->CREATE_ISTREAM_ITABLE( TABLE = XML_TABLE

SIZE = XML_TABLE_SIZE )

.

  • Create XML Document instance

DOCUMENT = G_IXML->CREATE_DOCUMENT( ).

  • Create parser Object

PARSER = G_IXML->CREATE_PARSER( STREAM_FACTORY = STREAMFACTORY

ISTREAM = ISTREAM

DOCUMENT = DOCUMENT ).

  • Parsing Error Processing

IF PARSER->PARSE( ) NE 0.

IF 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 = PARSER->NUM_ERRORS( ).

WRITE: COUNT, ' parse errors have occured:'.

INDEX = 0.

WHILE INDEX < COUNT.

PARSEERROR = PARSER->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.

  • Close the stream since it ís not needed anymore

CALL METHOD ISTREAM->CLOSE( ).

CLEAR ISTREAM.

DATA : GV_NODE TYPE REF TO IF_IXML_NODE.

DATA : GV_NODETEXT TYPE STRING.

DATA: GV_FIRST_TIME.

GV_FIRST_TIME = 'X'.

GV_NODE = DOCUMENT.

GT_ITEM-ITEM_NO = 1.

PERFORM GET_DATA TABLES GT_ITEM

USING GV_NODE

CHANGING GV_HEADER.

  • Last item is still not added.

APPEND GT_ITEM.

WRITE : GV_HEADER-CUST_NAME,

GV_HEADER-CARD_NO,

GV_HEADER-TAX_AMOUNT,

GV_HEADER-TOTAL_AMOUNT.

LOOP AT GT_ITEM.

WRITE /:.

WRITE : GT_ITEM-ITEM_NO,

GT_ITEM-ITEM_ID,

GT_ITEM-ITEM_TITLE,

GT_ITEM-ITEM_QTY,

GT_ITEM-ITEM_UPRICE.

ENDLOOP.

*----


*

  • FORM Get_data *

*----


*

FORM GET_DATA TABLES YT_ITEM STRUCTURE GT_ITEM

USING VALUE(X_NODE) TYPE REF TO IF_IXML_NODE

CHANGING Y_HEADER TYPE TY_HEADER.

DATA: INDENT TYPE I.

DATA: PTEXT TYPE REF TO IF_IXML_TEXT.

DATA: STRING TYPE STRING.

DATA: TEMP_STRING(100).

CASE X_NODE->GET_TYPE( ).

WHEN IF_IXML_NODE=>CO_NODE_ELEMENT.

STRING = X_NODE->GET_NAME( ).

GV_NODETEXT = STRING.

WHEN IF_IXML_NODE=>CO_NODE_TEXT.

PTEXT ?= X_NODE->QUERY_INTERFACE( IXML_IID_TEXT ).

IF PTEXT->WS_ONLY( ) IS INITIAL.

STRING = X_NODE->GET_VALUE( ).

CASE GV_NODETEXT.

WHEN 'Customer'.

CLEAR GV_HEADER.

WHEN 'Name'.

MOVE STRING TO GV_HEADER-CUST_NAME.

WHEN 'Cardnum'.

MOVE STRING TO GV_HEADER-CARD_NO.

WHEN 'Tax'.

MOVE STRING TO GV_HEADER-TAX_AMOUNT.

WHEN 'Total'.

MOVE STRING TO GV_HEADER-TOTAL_AMOUNT.

  • Item details

WHEN 'ID'.

MOVE STRING TO GT_ITEM-ITEM_ID.

WHEN 'Title'.

MOVE STRING TO TEMP_STRING.

MOVE TEMP_STRING TO GT_ITEM-ITEM_TITLE.

WHEN 'Quantity'.

MOVE STRING TO GT_ITEM-ITEM_QTY.

WHEN 'UnitPrice'.

MOVE STRING TO GT_ITEM-ITEM_UPRICE.

ENDCASE.

ENDIF.

ENDCASE.

IF GV_NODETEXT = 'Customer'.

CLEAR GV_HEADER.

ELSEIF GV_NODETEXT = 'Item'.

IF GV_FIRST_TIME NE 'X'.

APPEND GT_ITEM.

GT_ITEM-ITEM_NO = GT_ITEM-ITEM_NO + 1.

ENDIF.

GV_FIRST_TIME = ' '.

ENDIF.

  • Get the next child

X_NODE = X_NODE->GET_FIRST_CHILD( ).

  • Recurse

WHILE NOT X_NODE IS INITIAL.

PERFORM GET_DATA TABLES GT_ITEM

USING X_NODE

CHANGING GV_HEADER.

X_NODE = X_NODE->GET_NEXT( ).

ENDWHILE.

ENDFORM. "get_data

Regards,

Anbalagan

10 REPLIES 10
Read only

Former Member
0 Likes
4,876

Hi Ronald,

Could you go through the following code for XML to ABAP. I think it helps you a bit.

XML File

-

-


-

-


ABAP Coding

*&----


*

*& Report ZABN_XML_TO_ABAP *

*& *

*&----


*

REPORT ZABN_XML_TO_ABAP .

  • Load iXML Lib.

TYPE-POOLS: IXML.

CLASS CL_IXML DEFINITION LOAD.

DATA: G_IXML TYPE REF TO IF_IXML.

DATA: STREAMFACTORY TYPE REF TO IF_IXML_STREAM_FACTORY.

DATA: ISTREAM TYPE REF TO IF_IXML_ISTREAM.

DATA: DOCUMENT TYPE REF TO IF_IXML_DOCUMENT.

DATA: PARSER TYPE REF TO IF_IXML_PARSER.

DATA: LV_FILE_URL TYPE RLGRAP-FILENAME.

LV_FILE_URL = 'C:input_xml.xml'.

TYPES: BEGIN OF XML_LINE,

DATA(256) TYPE X,

END OF XML_LINE.

TYPES: BEGIN OF TY_HEADER,

CUST_NAME(20) TYPE C,

CARD_NO(20) TYPE C,

TAX_AMOUNT(10) TYPE C,

TOTAL_AMOUNT(10) TYPE C,

END OF TY_HEADER.

TYPES: BEGIN OF TY_ITEM,

ITEM_NO(4) TYPE N,

ITEM_ID(20) TYPE C,

ITEM_TITLE(50) TYPE C,

ITEM_QTY(10) TYPE C,

ITEM_UPRICE(10) TYPE C,

END OF TY_ITEM.

DATA: GV_HEADER TYPE TY_HEADER.

DATA: GT_ITEM TYPE STANDARD TABLE OF TY_ITEM WITH HEADER LINE.

DATA: XML_TABLE TYPE TABLE OF XML_LINE,

XML_TABLE_SIZE TYPE I.

  • The next step is creating the main factory for the iXML library:

G_IXML = CL_IXML=>CREATE( ).

  • Now Create Stream Factory

STREAMFACTORY = G_IXML->CREATE_STREAM_FACTORY( ).

  • upload a file from the client's workstation

CALL FUNCTION 'WS_UPLOAD'

EXPORTING

FILENAME = LV_FILE_URL

FILETYPE = 'BIN'

IMPORTING

FILELENGTH = XML_TABLE_SIZE

TABLES

DATA_TAB = XML_TABLE

EXCEPTIONS

OTHERS = 11.

  • wrap the table containing the file into a stream

ISTREAM = STREAMFACTORY->CREATE_ISTREAM_ITABLE( TABLE = XML_TABLE

SIZE = XML_TABLE_SIZE )

.

  • Create XML Document instance

DOCUMENT = G_IXML->CREATE_DOCUMENT( ).

  • Create parser Object

PARSER = G_IXML->CREATE_PARSER( STREAM_FACTORY = STREAMFACTORY

ISTREAM = ISTREAM

DOCUMENT = DOCUMENT ).

  • Parsing Error Processing

IF PARSER->PARSE( ) NE 0.

IF 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 = PARSER->NUM_ERRORS( ).

WRITE: COUNT, ' parse errors have occured:'.

INDEX = 0.

WHILE INDEX < COUNT.

PARSEERROR = PARSER->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.

  • Close the stream since it ís not needed anymore

CALL METHOD ISTREAM->CLOSE( ).

CLEAR ISTREAM.

DATA : GV_NODE TYPE REF TO IF_IXML_NODE.

DATA : GV_NODETEXT TYPE STRING.

DATA: GV_FIRST_TIME.

GV_FIRST_TIME = 'X'.

GV_NODE = DOCUMENT.

GT_ITEM-ITEM_NO = 1.

PERFORM GET_DATA TABLES GT_ITEM

USING GV_NODE

CHANGING GV_HEADER.

  • Last item is still not added.

APPEND GT_ITEM.

WRITE : GV_HEADER-CUST_NAME,

GV_HEADER-CARD_NO,

GV_HEADER-TAX_AMOUNT,

GV_HEADER-TOTAL_AMOUNT.

LOOP AT GT_ITEM.

WRITE /:.

WRITE : GT_ITEM-ITEM_NO,

GT_ITEM-ITEM_ID,

GT_ITEM-ITEM_TITLE,

GT_ITEM-ITEM_QTY,

GT_ITEM-ITEM_UPRICE.

ENDLOOP.

*----


*

  • FORM Get_data *

*----


*

FORM GET_DATA TABLES YT_ITEM STRUCTURE GT_ITEM

USING VALUE(X_NODE) TYPE REF TO IF_IXML_NODE

CHANGING Y_HEADER TYPE TY_HEADER.

DATA: INDENT TYPE I.

DATA: PTEXT TYPE REF TO IF_IXML_TEXT.

DATA: STRING TYPE STRING.

DATA: TEMP_STRING(100).

CASE X_NODE->GET_TYPE( ).

WHEN IF_IXML_NODE=>CO_NODE_ELEMENT.

STRING = X_NODE->GET_NAME( ).

GV_NODETEXT = STRING.

WHEN IF_IXML_NODE=>CO_NODE_TEXT.

PTEXT ?= X_NODE->QUERY_INTERFACE( IXML_IID_TEXT ).

IF PTEXT->WS_ONLY( ) IS INITIAL.

STRING = X_NODE->GET_VALUE( ).

CASE GV_NODETEXT.

WHEN 'Customer'.

CLEAR GV_HEADER.

WHEN 'Name'.

MOVE STRING TO GV_HEADER-CUST_NAME.

WHEN 'Cardnum'.

MOVE STRING TO GV_HEADER-CARD_NO.

WHEN 'Tax'.

MOVE STRING TO GV_HEADER-TAX_AMOUNT.

WHEN 'Total'.

MOVE STRING TO GV_HEADER-TOTAL_AMOUNT.

  • Item details

WHEN 'ID'.

MOVE STRING TO GT_ITEM-ITEM_ID.

WHEN 'Title'.

MOVE STRING TO TEMP_STRING.

MOVE TEMP_STRING TO GT_ITEM-ITEM_TITLE.

WHEN 'Quantity'.

MOVE STRING TO GT_ITEM-ITEM_QTY.

WHEN 'UnitPrice'.

MOVE STRING TO GT_ITEM-ITEM_UPRICE.

ENDCASE.

ENDIF.

ENDCASE.

IF GV_NODETEXT = 'Customer'.

CLEAR GV_HEADER.

ELSEIF GV_NODETEXT = 'Item'.

IF GV_FIRST_TIME NE 'X'.

APPEND GT_ITEM.

GT_ITEM-ITEM_NO = GT_ITEM-ITEM_NO + 1.

ENDIF.

GV_FIRST_TIME = ' '.

ENDIF.

  • Get the next child

X_NODE = X_NODE->GET_FIRST_CHILD( ).

  • Recurse

WHILE NOT X_NODE IS INITIAL.

PERFORM GET_DATA TABLES GT_ITEM

USING X_NODE

CHANGING GV_HEADER.

X_NODE = X_NODE->GET_NEXT( ).

ENDWHILE.

ENDFORM. "get_data

Regards,

Anbalagan

Read only

0 Likes
4,875

Anbalagan Velu - your solution has got me on my way, thanks. I have a problem though. I am receiving an XML file that is going to a UNIX box. I am trying to use logical directories to get the file using open dataset. When I do this I get an XML error from the parsing. I used the same file in both programs but the one using open dataset doesn't work. Is there some other way to use the logical directories to get the file uploaded. As far as I know I can use WS)UPLOAD because I am not accessing via presentation server.

I am on 4.6C

Thanks for your help.

Mike

Read only

0 Likes
4,875

Did you "open dataset IN BINARY MODE "?

Also try populating xml_itab of width 256 TYPE X,

you need to get the exact size of file as well.

you might try FM 'EPS_GET_FILE_ATTRIBUTES' for this.

cheers,

Ram

Message was edited by: Ram Manohar Tiwari

Read only

0 Likes
4,875

Is there a way to determine what is in between the " " (quotes) on each tag shown below? I need to do different stuff depending on what partnerRoleIndicator it is.

Thanks,

Mike

<pidx:PartnerInformation partnerRoleIndicator="Carrier">

<pidx:PartnerIdentifier partnerIdentifierIndicator="AssignedByCarrier">CPL</pidx:PartnerIdentifier>

<pidx:PartnerName>Colonial Pipeline Company</pidx:PartnerName>

<pidx:AddressInformation>

<pidx:AddressLine>P.O. Box 18855</pidx:AddressLine>

<pidx:CityName>Atlanta</pidx:CityName>

<pidx:StateProvince>GA</pidx:StateProvince>

<pidx:PostalCode>31126</pidx:PostalCode>

</pidx:AddressInformation><pidx:ContactInformation contactInformationIndicator="EnteredBy">

<pidx:ContactIdentifier contactIdentifierIndicator="AssignedByCarrier">matthew_hommes</pidx:ContactIdentifier>

<pidx:ContactDescription>Entered by Carrier</pidx:ContactDescription>

</pidx:ContactInformation>

</pidx:PartnerInformation>

<pidx:PartnerInformation partnerRoleIndicator="Marketplace">

<pidx:PartnerIdentifier partnerIdentifierIndicator="DUNSNumber">143930217</pidx:PartnerIdentifier>

<pidx:PartnerName>Transport4</pidx:PartnerName>

</pidx:PartnerInformation>

<pidx:PartnerInformation partnerRoleIndicator="FinalRecipient">

<pidx:PartnerIdentifier partnerIdentifierIndicator="AssignedByCarrier">CIT</pidx:PartnerIdentifier>

<pidx:PartnerName>company Corp.</pidx:PartnerName>

</pidx:PartnerInformation>

Read only

0 Likes
4,875

Nevermind, I figured it out, had to get the attributes and then from that node get the name and value.

thanks all sample code below.

DATA: NODE2 TYPE REF TO IF_IXML_NODE.

DATA: ATTRIBUTES TYPE REF TO IF_IXML_NAMED_NODE_MAP.

ATTRIBUTES = X_NODE->GET_ATTRIBUTES( ).

CALL METHOD ATTRIBUTES->GET_NAMED_ITEM

EXPORTING

NAME = 'partnerRoleIndicator'

  • NAMESPACE = ''

RECEIVING

RVAL = NODE2.

STRING3 = NODE2->GET_VALUE( ).

STRING4 = NODE2->GET_NAME( ).

Read only

athavanraja
Active Contributor
0 Likes
4,875

Welcome to SDN

1. within the xslt when you refer to itab name & fields, use all uppercase.

2. replace the <DOCUMENT> with <ITAB_DOCUMENT> and the filed names to upper case

3. CALL TRANSFORMATION zrappel_xml_test

SOURCE XML itab_upload

RESULT document = itab_document<b>[]</b> .

4. CALL TRANSFORMATION zrappel_xml_test

SOURCE XML <b>itab_upload</b> " it has to be a string not itab

RESULT document = itab_document.

check out.

https://www.sdn.sap.com/sdn/url.sdn?res=/irj/servlet/prt/portal/prtroot/com.sap.km.cm.docs/library/u...

Hope this helps.

Regards

Raja

Message was edited by: Durairaj Athavan Raja

Read only

0 Likes
4,875

> Welcome to SDN

> 4. CALL TRANSFORMATION zrappel_xml_test

> SOURCE XML <b>itab_upload</b> " it has to be a string

> not itab

> RESULT document = itab_document.

>

>

Thanks for your help.

itab_upload is a table with one field, this is a c(255). according to the sap-help this should be possible...

Read only

0 Likes
4,875

thanks for sharing the info. i have always used string for XML content.

Regards

Raja

Read only

Former Member
0 Likes
4,875

hi, though the topic is close, I think I need to add something in the end.

if you want to use XSLT way, only need to do some change on your XSLT, like following:

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

<xsl:strip-space elements="*"/>

<xsl:template match="F">

<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">

<asx:values>

<DOCUMENT>

<xsl:apply-templates/>

</DOCUMENT>

</asx:values>

</asx:abap>

</xsl:template>

<xsl:template match="P1">

<b><ENTRY></b>

<b><T_1></b><xsl:value-of select="t_1"/><b></T_1></b>

<b><T_2></b><xsl:value-of select="t_2"/><b></T_2></b>

<b></ENTRY></b>

</xsl:template>

</xsl:transform>

<ENTRY> is just for encapsulate the entry of internal table, it is necessary, but the name is random.

<T_1> .. as raja said, the fields name should be upper case.

Hope it will be helpful

thanks

Read only

Former Member
0 Likes
4,875

Hi All,

This is with reference to my post dated Sep 6th,2005 related to Converting XML into ABAP, the code I pasted works fine for Ver 4.6c and in 4.7 there are some features available for this.

For further informations please have a look at www.rmtiwari.com.

Regards,

Anbalagan.V