‎2005 Sep 06 9:10 AM
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
‎2005 Sep 06 9:59 AM
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
‎2005 Sep 06 9:59 AM
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
‎2005 Oct 14 9:56 PM
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
‎2005 Oct 14 11:50 PM
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
‎2005 Oct 18 8:39 PM
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>
‎2005 Oct 19 8:12 PM
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( ).
‎2005 Sep 06 10:40 AM
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.
Hope this helps.
Regards
Raja
Message was edited by: Durairaj Athavan Raja
‎2005 Sep 06 11:15 AM
> 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...
‎2005 Sep 06 11:24 AM
thanks for sharing the info. i have always used string for XML content.
Regards
Raja
‎2005 Sep 06 3:45 PM
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
‎2005 Sep 22 6:37 AM
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