2006 Dec 04 9:31 AM
Hello all,
I have an xml stored in a string. Its format is as below:
<?xml version="1.0" encoding="utf-8"?>
......
<QfiData xmlns="http://www2.siemens.nl/qfiservice/QfiData.xsd">
<Material diffgr:id="Material1" msdata:rowOrder="0">
<Material>463581</Material>
<ConditionRate> 2.44</ConditionRate>
<ValidFrom>20060208</ValidFrom>
<ValidTo>99991231</ValidTo>
<RegionID>48</RegionID>
<MaterialID>36294</MaterialID>
</Material>
<Material diffgr:id="Material2" msdata:rowOrder="1">
<Material>463582</Material>
<ConditionRate> 2.44</ConditionRate>
<ValidFrom>20060208</ValidFrom>
<ValidTo>99991231</ValidTo>
<RegionID>48</RegionID>
<MaterialID>36295</MaterialID>
</Material>
.....
Now the question is, i want to read only the child nodes of Material i.e., material, condition rate, validfrom, valid to, regionid, materilid and store these in an internal table.
Can anyone help me.
Thankyou.
2006 Dec 04 10:09 AM
XLST program code (YSIMPLEXMLTOITAB)
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:strip-space elements="*"/>
<xsl:output indent="yes"/>
<xsl:template match="QfiData">
<asx:abap xmlns:asx="http://www.sap.com/abapxml">
<asx:values>
<I_DATA>
<xsl:for-each select="Materials">
<I_DATA1>
<MATERIAL>
<xsl:value-of select="Material"/>
</MATERIAL>
<CONDITIONRATE>
<xsl:value-of select="ConditionRate"/>
</CONDITIONRATE>
<VALIDFROM>
<xsl:value-of select="ValidFrom"/>
</VALIDFROM>
<VALIDTO>
<xsl:value-of select="ValidTo"/>
</VALIDTO>
<REGIONID>
<xsl:value-of select="RegionID"/>
</REGIONID>
<MATERIALID>
<xsl:value-of select="MaterialID"/>
</MATERIALID>
</I_DATA1>
</xsl:for-each>
</I_DATA>
</asx:values>
</asx:abap>
</xsl:template>
</xsl:stylesheet>
Program to test it.
REPORT y_test_xml_tran.
TYPES: BEGIN OF i_det,
Material(10),
ConditionRate(16) type p decimals 2 ,
ValidFrom(10) ,
ValidTo(10) ,
RegionID(3) ,
MaterialID(10) ,
end of i_det .
DATA: i_data TYPE TABLE OF i_det.
data: wa like line of i_data .
DATA: xml_string TYPE string .
DATA: xslt_error TYPE REF TO cx_xslt_exception,
xslt_message TYPE string .
CLEAR xml_string .
CONCATENATE
`<?xml version="1.0" encoding="utf-8"?>`
`<QfiData xmlns:xsl="http://www2.siemens.nl/qfiservice/QfiData.xsd">`
`<Materials>`
`<Material>463581</Material>`
`<ConditionRate> 2.44</ConditionRate>`
`<ValidFrom>20060208</ValidFrom>`
`<ValidTo>99991231</ValidTo>`
`<RegionID>48</RegionID>`
`<MaterialID>36294</MaterialID>`
`</Materials>`
`<Materials>`
`<Material>463582</Material>`
`<ConditionRate> 2.44</ConditionRate>`
`<ValidFrom>20060208</ValidFrom>`
`<ValidTo>99991231</ValidTo>`
`<RegionID>48</RegionID>`
`<MaterialID>36295</MaterialID>`
`</Materials>`
`</QfiData>`
INTO xml_string .
TRY .
CALL TRANSFORMATION (`YSIMPLEXMLTOITAB`)
SOURCE XML xml_string
RESULT i_data = i_data.
CATCH cx_xslt_exception INTO xslt_error.
xslt_message = xslt_error->get_text( ).
ENDTRY.
Regards
Raja
2006 Dec 04 9:47 AM
Hi Bobby,
1. Prepare a local file from XML document by Calling the method IMPORT_FROM_FILE of class CL_XML_DOCUMENT_BASE .
2.For converting file to internal table, call the Funciton module GUI_DOWLOAD you can get all entries in internal table. (By passing input from the above step)
Regards
Bhupal Reddy
2006 Dec 04 10:13 AM
hello bhupal,
1. I have the data in a <b>string</b> in the program.
2. i don't want all the data into an internal table, i want to traverse or read only particular nodes and get the data of nodes material, validfrom,validto.. to an internal table.
2006 Dec 04 10:09 AM
XLST program code (YSIMPLEXMLTOITAB)
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:strip-space elements="*"/>
<xsl:output indent="yes"/>
<xsl:template match="QfiData">
<asx:abap xmlns:asx="http://www.sap.com/abapxml">
<asx:values>
<I_DATA>
<xsl:for-each select="Materials">
<I_DATA1>
<MATERIAL>
<xsl:value-of select="Material"/>
</MATERIAL>
<CONDITIONRATE>
<xsl:value-of select="ConditionRate"/>
</CONDITIONRATE>
<VALIDFROM>
<xsl:value-of select="ValidFrom"/>
</VALIDFROM>
<VALIDTO>
<xsl:value-of select="ValidTo"/>
</VALIDTO>
<REGIONID>
<xsl:value-of select="RegionID"/>
</REGIONID>
<MATERIALID>
<xsl:value-of select="MaterialID"/>
</MATERIALID>
</I_DATA1>
</xsl:for-each>
</I_DATA>
</asx:values>
</asx:abap>
</xsl:template>
</xsl:stylesheet>
Program to test it.
REPORT y_test_xml_tran.
TYPES: BEGIN OF i_det,
Material(10),
ConditionRate(16) type p decimals 2 ,
ValidFrom(10) ,
ValidTo(10) ,
RegionID(3) ,
MaterialID(10) ,
end of i_det .
DATA: i_data TYPE TABLE OF i_det.
data: wa like line of i_data .
DATA: xml_string TYPE string .
DATA: xslt_error TYPE REF TO cx_xslt_exception,
xslt_message TYPE string .
CLEAR xml_string .
CONCATENATE
`<?xml version="1.0" encoding="utf-8"?>`
`<QfiData xmlns:xsl="http://www2.siemens.nl/qfiservice/QfiData.xsd">`
`<Materials>`
`<Material>463581</Material>`
`<ConditionRate> 2.44</ConditionRate>`
`<ValidFrom>20060208</ValidFrom>`
`<ValidTo>99991231</ValidTo>`
`<RegionID>48</RegionID>`
`<MaterialID>36294</MaterialID>`
`</Materials>`
`<Materials>`
`<Material>463582</Material>`
`<ConditionRate> 2.44</ConditionRate>`
`<ValidFrom>20060208</ValidFrom>`
`<ValidTo>99991231</ValidTo>`
`<RegionID>48</RegionID>`
`<MaterialID>36295</MaterialID>`
`</Materials>`
`</QfiData>`
INTO xml_string .
TRY .
CALL TRANSFORMATION (`YSIMPLEXMLTOITAB`)
SOURCE XML xml_string
RESULT i_data = i_data.
CATCH cx_xslt_exception INTO xslt_error.
xslt_message = xslt_error->get_text( ).
ENDTRY.
Regards
Raja
2006 Dec 04 10:16 AM
2006 Dec 04 10:24 AM
which version of R/3 you are using?
the code i had given can only be used in WAS6.10 or above (4.7)
to create XSLT program go to transaction Se80-> click on the button edit object->in the resulting dialog choose transformation radiobutton->enter name and click create. in the resulting editor, copy paste the xslt code given.
Regards
Raja
2006 Dec 04 10:55 AM
hello raj,
I have created the XLST program as below and implemented the logic.
<xsl:transform version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:sapxsl="http://www.sap.com/sapxsl"
>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:strip-space elements="*"/>
<xsl:output indent="yes"/>
<xsl:template match="QfiData">
<asx:abap xmlns:asx="http://www.sap.com/abapxml">
<asx:values>
<I_DATA>
<xsl:for-each select="Materials">
<I_DATA1>
<MATERIAL>
<xsl:value-of select="Material"/>
</MATERIAL>
<CONDITIONRATE>
<xsl:value-of select="ConditionRate"/>
</CONDITIONRATE>
<VALIDFROM>
<xsl:value-of select="ValidFrom"/>
</VALIDFROM>
<VALIDTO>
<xsl:value-of select="ValidTo"/>
</VALIDTO>
<REGIONID>
<xsl:value-of select="RegionID"/>
</REGIONID>
<MATERIALID>
<xsl:value-of select="MaterialID"/>
</MATERIALID>
</I_DATA1>
</xsl:for-each>
</I_DATA>
</asx:values>
</asx:abap>
</xsl:template>
</xsl:stylesheet>
</xsl:transform>
But i am getting an error as below:
xlst:message = ABAP XML formatting error in XML node of type "element", name: "abap".
could you please help me.
2006 Dec 04 11:35 AM
remove the following lines from your XSLT program
<xsl:transform version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:sapxsl="http://www.sap.com/sapxsl"
>
&
</xsl:transform>
Raja
2006 Dec 04 12:46 PM
hello raja,
thankyou. the example code is working very good. but i still have problem when i try to implement it with the actual program.
I am getting this error: <b> ABAP XML formatting error in XML node of type "element", name: "abap"
2006 Dec 04 12:50 PM
Hello raja,
Is it necessary that QfiData should be the starting tag. Actually i have a complex/huge xml file. From that file i have read only the material details.
The actual xml file looks as below:
<?xml version="1.0" encoding="utf-8"?>
<DataSet xmlns="http://www2.siemens.nl/qfiservice">
<xs:schema id="QfiData" targetNamespace="http://www2.siemens.nl/qfiservice/QfiData.xsd" xmlns:mstns="http://www2.siemens.nl/qfiservice/QfiData.xsd" xmlns="http://www2.siemens.nl/qfiservice/QfiData.xsd" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" attributeFormDefault="qualified" elementFormDefault="qualified">
<xs:element name="QfiData" msdata:IsDataSet="true" msdata:UseCurrentLocale="true">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="Material">
<xs:complexType>
<xs:sequence>
<xs:element name="Material" type="xs:int" minOccurs="0" />
<xs:element name="ConditionRate" minOccurs="0">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="50" />
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="ValidFrom" msdata:ReadOnly="true" minOccurs="0">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="8" />
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="ValidTo" msdata:ReadOnly="true" minOccurs="0">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="8" />
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="RegionID" msdata:ReadOnly="true" type="xs:int" minOccurs="0" />
<xs:element name="MaterialID" msdata:ReadOnly="true" msdata:AutoIncrement="true" type="xs:int" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="Pricegroup">
<xs:complexType>
<xs:sequence>
<xs:element name="ConditionRate" minOccurs="0">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="50" />
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="PricegroupCpServ" minOccurs="0">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="50" />
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="ValidFrom" msdata:ReadOnly="true" minOccurs="0">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="8" />
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="ValidTo" msdata:ReadOnly="true" minOccurs="0">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="8" />
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="RegionID" msdata:ReadOnly="true" type="xs:int" minOccurs="0" />
<xs:element name="PricegroupID" msdata:ReadOnly="true" msdata:AutoIncrement="true" type="xs:int" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
<xs:unique name="Constraint1" msdata:PrimaryKey="true">
<xs:selector xpath=".//mstns:Material" />
<xs:field xpath="mstns:MaterialID" />
</xs:unique>
<xs:unique name="Pricegroup_Constraint1" msdata:ConstraintName="Constraint1" msdata:PrimaryKey="true">
<xs:selector xpath=".//mstns:Pricegroup" />
<xs:field xpath="mstns:PricegroupID" />
</xs:unique>
</xs:element>
</xs:schema>
<diffgr:diffgram xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1">
<QfiData xmlns="http://www2.siemens.nl/qfiservice/QfiData.xsd">
<Material diffgr:id="Material1" msdata:rowOrder="0">
<Material>463581</Material>
<ConditionRate> 2.44</ConditionRate>
<ValidFrom>20060208</ValidFrom>
<ValidTo>99991231</ValidTo>
<RegionID>48</RegionID>
<MaterialID>36294</MaterialID>
</Material>
<Material diffgr:id="Material2" msdata:rowOrder="1">
<Material>463582</Material>
<ConditionRate> 2.44</ConditionRate>
<ValidFrom>20060208</ValidFrom>
<ValidTo>99991231</ValidTo>
<RegionID>48</RegionID>
<MaterialID>36295</MaterialID>
</Material>
<Material diffgr:id="Material3" msdata:rowOrder="2">
<Material>461691</Material>
<ConditionRate> 4.96</ConditionRate>
<ValidFrom>20060208</ValidFrom>
<ValidTo>99991231</ValidTo>
<RegionID>48</RegionID>
<MaterialID>36296</MaterialID>
</Material>
2006 Dec 04 12:52 PM
if you look at the example , i have slightly modified the XML, may be post the actual XML file, i will come up with the suggestion.
Regards
Raja
Awarding points to helpful posts is SDN way of saying thanks. you can do this by choosing appropriate radiobuttons in the answers
2006 Dec 04 1:14 PM
try this alternate approach, in the mean time you can mail me the actual XML file (you can find my id in the business card) i will come up with the XSLT program.
report y_xml_upload
no standard page heading.
data: filename type string ,
xmldata type xstring .
data: result_xml type standard table of smum_xmltb .
data: return type standard table of bapiret2 .
constants: line_size type i value 255.
data: begin of xml_tab occurs 0,
raw(line_size) type x,
end of xml_tab,
file type string,
size type i.
* upload the xml file
filename = 'C:rajabw.xml' .
call function 'GUI_UPLOAD'
exporting
filename = filename
filetype = 'BIN'
has_field_separator = ' '
header_length = 0
importing
filelength = size
tables
data_tab = xml_tab
exceptions
others = 1.
************uncomment this and comment the call of SCMS_BINARY_TO_XSTRING if you dont have this fm in your system.
* if sy-subrc <> 0.
* clear: xmldata.
* exit.
* else.
* data: len type i.
* len = size.
* loop at xml_tab.
* if len <= line_size. exit. endif.
* concatenate xmldata xml_tab-raw(line_size)
* into xmldata in byte mode.
* len = len - line_size.
* endloop.
* if len > 0.
* concatenate xmldata xml_tab-raw(len)
* into xmldata in byte mode.
* len = len - size.
* endif.
* endif.
******* end of comment.
call function 'SCMS_BINARY_TO_XSTRING'
exporting
input_length = size
* FIRST_LINE = 0
* LAST_LINE = 0
importing
buffer = xmldata
tables
binary_tab = xml_tab
exceptions
failed = 1
others = 2
.
if sy-subrc <> 0.
* MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
* WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
endif.
call function 'SMUM_XML_PARSE'
exporting
xml_input = xmldata
tables
xml_table = result_xml
return = return .
Regards
Raja
2006 Dec 05 7:49 AM
Hi raja,
Still the problem exists:
Error message : ABAP XML formatting error in XML node of type "element", name: "abap"
2006 Dec 05 8:44 AM
i tried the alternate approach suggested (byme) with the file you had sent and it works fine.
(youhave to change the file location in the code filename = 'C:\...material.xml' .).
the only difference in this method is all xml elements are stored in the tab as name value pair, which you have to loop thru to get the data.
Regards
Raja
2006 Dec 05 10:18 AM
hello raja,
could you please check the gmail for the latest query. i will send you the code, xml file and xslt.
actually the example program works fine. when when i try to import the actual xml file. there is an error.
please have a look and help me.
2006 Dec 05 10:32 AM
the problem, is that the following mandatory line is nt there in the xml file.
<?xml version="1.0" encoding="utf-8"?> , it has to be there.
Regards
Raja
2006 Dec 05 10:40 AM
i am sorry raja. i have already check that. no good result even if i include the
<?xml version="1.0" encoding="utf-8"?> mandatory string.
2006 Dec 05 1:00 PM
hi raja,
Thank you very much. The alternative method is working fine. points rewarded.
But i would like know couple of things:
1. As you know i don't upload the data. But i get the xml file as a response and i have xml file in "xml_string" in text mode. Now i want to use the "SMUM_XML_PARSE".
Can you just tell me how?
2006 Dec 05 1:06 PM
data: xml_string type string ,
xml_xstring type xstring ,
encoding type abap_encoding ,
applencoding type cpcodepage.
call function 'SCP_GET_CODEPAGE_NUMBER'
importing
appl_codepage = applencoding.
encoding = applencoding.
call function 'SCMS_STRING_TO_XSTRING'
exporting
text = xml_string
encoding = encoding
importing
buffer = xml_xstring
exceptions
failed = 1
others = 2.
now you can use xml_xstring with the function module.
Regards
Raja
2006 Dec 05 1:15 PM
hi raja.
Super. Thats great man. Its works perfectly. Thank you very much.
2006 Dec 05 1:30 PM
hi raja,
I am still interested to know about the mistake in XSLT. It was woking fine for the example code but not for the business requirement.
I would like to know the solution can you help me in this regard. i will be writing a new thread. As you the subject very well. Please do answer to that thread.
2006 Dec 04 10:13 AM
HI,
See the below links, this is useful for you
/people/tobias.trapp/blog/2006/10/06/xml-processing-in-abap-part-9-150-abap-processing-using-xslt
http://searchtechtarget.techtarget.com/generic/0,295582,sid21_gci1207657,00.html
Regards
Sudheer
2006 Dec 04 10:42 AM