XML and SAP
Since today is Thanksgiving, and we'll all be consuming lots of Turkey, I thought I would show you and example of how SAP can consume XML :) (Sorry, best segue i could come up with :>)
Using XML as a way of import information into SAP is something that you are going to see a lot more of in the future. There is some help on the subject and what I am posting below is a mixture of that help and a working ABAP program constructed from it. So although putting it together and making it work was me, the real credit goes to the whomever at SAP wrote this in the first place. You should be able to copy and paste this into a new program in SE38, and just rename the xml file as needed.
If all of the above is greek to you, go enjoy some Turkey, 'cos it ain't about to get any better :>
REPORT (sy-repid) MESSAGE-ID z_pay_common LINE-SIZE 255 LINE-COUNT 65
NO STANDARD PAGE HEADING.
* Note: This is all from
* iXML ABAP Objects Jumpstart
* Next step after this is Casting up and down the DOM Hierarchy.
* In order to enable the iXML library, you have to add the following
* lines to your code:
class cl_ixml definition load.
*The next step is creating the main factory for the iXML library:
data: g_ixml type ref to if_ixml.
g_ixml = cl_ixml=>create( ).
* You will need only one such factory in a program, so it makes sense to
* place the statement above in the initialization section of your
* program and make g_ixml a global variable. If you try to instantiate
* the iXML factory more than once in a program, you'll only get
* references to the first instance created (singleton).
* Now you are already done. The iXML library is ready for use and the
* next steps depend on what you actually want to accomplish.
* Usually your program will require some form of input or output. The
* iXML library therefore provides a number of different streams you can
* use for XML document I/O. The object that constructs these streams is
* an cl_ixml_stream_factory object, which can be created by the iXML
* factory with the following statement:
data: streamFactory type ref to if_ixml_stream_factory.
streamFactory = g_ixml->create_stream_factory( ).
* Now you are ready to create e.g. an input stream that can be used to
* read from a file in your machine's file system:
data iStream type ref to if_ixml_istream.
* Or you can wrap an internal (unstructured) table into a stream to pass
* it to the parser. The table is then assumed to contain a line-wrapped
* XML document:
TYPES: BEGIN OF xml_line,
data(256) type X,
END OF xml_line.
data: xml_table type table of xml_line,
xml_table_size type i.
DATA: WA_XML LIKE XML_TABLE OCCURS 0.
* When parsing an XML document you will simply pass the stream to the
* parser. The actual source behind the stream doesn't matter. For a list
* of available streams check the if_ixml_stream_factory interface.
* iStream = streamFactory->create_istream_uri( "file://c:\test.xml" ).
* iStream = streamFactory->create_istream_uri( "http://www.weather.
* gov/data/current_obs/KDFW.xml" ).
* upload a file from the client's workstation
call function 'WS_UPLOAD'
filename = '\\VAUGHAN_LAPTOP\C$\test.xml'
filetype = 'BIN'
filelength = xml_table_size
data_tab = xml_table
others = 11.
* wrap the table containing the file into a stream
istream = streamFactory->create_istream_itable( table = xml_table
size = xml_table_size ).
* You can of course have several cl_ixml_document objects in parallel.
* Now you are ready to get your hands dirty and parse an XML document.
* The next section will tell you how...
* Creating a document
* No matter whether you parse an XML document or create one from scratch
* with your program and then render it into a stream, you always need
* some object to store the document for you while you handle it with
* your code. The object you need is an cl_ixml_document object and it's
* easy to get one from the iXML factory:
data: document type ref to if_ixml_document.
document = g_ixml->create_document( ).
* As mentioned earlier, parsing an XML document can be done in two ways:
* either creating a DOM representation of the XML document, or by the
* parser firing events as logical elements are encountered in a run
* through an XML document. This section covers DOM-based parsing.
* What you will need to create a DOM representation of an XML document
* are the following objects:
* As always, you will need the cl_ixml main factory. In addition to that
* we will need a cl_ixml_stream_factory object to create the input
* stream from. Then there must be place to store the DOM-tree in. A
* cl_ixml_document object is the answer. The previous section Basic
* steps in your program tells you how to create these objects.
* In order to parse a document, you will also need a cl_ixml_parser
* object. The Parser can be obtained from the iXML factory by the
* following call:
data: parser type ref to if_ixml_parser.
parser = g_ixml->create_parser( stream_factory = streamFactory
istream = iStream
document = document ).
* A cl_ixml_parser object is a "use once and throw away" object. That
* means that you create a new cl_ixml_parser, call it to parse one
* document and then throw the parser object away. There is no way of
* reusing the parser for an additional XML document.
* Our goal was to parse an XML document into a DOM tree, so here we go
* parser->parse( ).
* That's it. If there haven't been any errors in the XML document we
* just parsed from the input stream provided, then the document object
* we passed to the factory method of the parser will now contain the DOM
* representation we were looking for.
* Since errors usually happen, we should try to play this game a little
* bit safer, do some error checking and print out diagnostic messages:
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 < parseerror =" parser-">get_error( index = index ).
i = parseError->get_line( ).
write: 'line: ', i.
i = parseError->get_column( ).
write: 'column: ', i.
str = parseError->get_reason( ).
index = index + 1.
*Getting access to the root element
*As you have seen in the previous sections, a cl_ixml_documentinstance
*always holds the complete DOM tree. One of the immediate child nodes
* of the cl_ixml_document is the root element of the XML document. The
* following call will give you access to this node:
data: element type ref to if_ixml_element.
element = document->get_root_element( ).
* Now you have a good starting point to look at the rest of the document
* Getting access to a node's children
* There are two ways to traverse the child nodes of a node, e.g. the
* cl_ixml_elementnodes of an cl_ixml_element node. One is to first
* navigate to the first child node and then ask this node to return the
* next (sibling) node. This approach looks like that:
* data: child type ref to if_ixml_node.
* child = element->get_first_child( ).
* while not child is initial.
** do something with the node
* child = child->get_next( ).
* The W3C DOM also defined a method to return a list of nodes, a
* cl_ixml_node_listinstance providing index-based access to the child
* nodes of a node:
data: nodes type ref to if_ixml_node_list,
child type ref to if_ixml_node.
data attribute type ref to if_ixml_attribute.
nodes = element->get_children( ).
index = 0.
while index <>get_length( ).
child = nodes->get_item( index ).
attribute ?= child->query_interface( ixml_iid_attribute ).
* do something with the node
index = index + 1.
* Even though index-based access is guaranteed to perform in constant
* time (O(1)) for sequential indizes (e.g. 1,2,3,..,n or n,..,3,2,1),
* using cl_ixml_node_list for random-access will usually degrade to
* linear lookup (O(n)).
* Recursively using one of the two approaches above will of course allow
* you to traverse the whole DOM tree.
WRITE 'ALL DONE'.
* Now you can do whatever you want with the cl_ixml_documentobject you
* passed to the parser.