XML Data Exchange Using Abap
XML Data Exchange Using Abap
Tobias Trapp
Contents
www.sap-press.com 1
Contents
www.sap-press.com 3
4 XSL Transformations
Since Release 6.10 of the SAP Web Application Server ( http://www.w3.org/TR/xpath ). In the following sections,
( SAP Web AS ), XSL Transformations ( XSLT ) have been we’ll assume that you’re familiar with XPath 1.0 and we’ll
integrated in ABAP via the CALL TRANSFORMATION com- discuss only those extensions that SAP has implemented
mand. When the XSLT processor was implemented, the in the XSLT processor. Some of those extensions are only
current XSLT 2.0 specification was still under discussion. available as of SAP Kernel Release 6.20.
For this reason, a version was implemented that is based
on the “W3C Working Draft,” on April 30, 2002 ( http://
www.w3.org/TR/2002/WD-xslt20-20020430 ). Because 4.1 Integrating XSLT into the ABAP Work-
we cannot assume that this working draft is generally well bench
known, we’ll compare it with the current version during
the course of this chapter: the “W3C Candidate Recom- You can create XSLT programs via Transaction SE80. To do
mendation” of November 3, 2005 ( http://www.w3.org/ that, you must go to the package view, then right-click
TR/2005/CR-xslt20-20051103 ). on a package to open its context menu and select Cre-
The importance of XSLT for data exchange stems from ate · More... · Transformation. An input dialog displays,
the fact that it is the most powerful and advanced tech- as shown in Figure 4.1. Then you can edit the program in
nology available for the transformation of XML docu- an editor.
ments. XML data can be transformed into ABAP data Figure 4.2 shows a sample transformation that
structures and vice versa; however, XSLT is not limited to searches all elements of an XML document recursively
those types of output. You can also generate HTML docu- and outputs a message for each A element. This exam-
ments or plain text files that are made available as load- ple already shows some facts: The root element of the
able assets to other applications. transformation is the xsl:transform element. This ele-
XSLT is widely used and well documented by a vast ment has the same functionality as the xsl:stylesheet
number of resources. Because you can easily integrate statement. Which command you want to use is purely
existing XML transformations in ABAP, you can also reuse subjective; however, it has become common practice to
existing XSLT-based data exchange solutions in an SAP refer to transformations that format XML documents in a
system. readable way as stylesheets, whereas in the data exchange
Elements and attributes in the tree structure of an XML context they are called transformations.
document are addressed in a specific language: XPath
www.sap-press.com 29
4 XSL Transformations
When the XSLT Tester runs the transformation with the Figure 4.4 shows an output of the debugger for the sam-
above input, it returns the output shown in Figure 4.3. ple transformation.
You can call the XSLT Tester from Transaction SE80 by The output of messages is necessary for testing the
highlighting a transaction and clicking on the Test XSLT process and error behavior of a transformation. Because
Program button. you can use messages for manual testing, Section 4.2
You can also execute XSLT programs step by step. shows how you can do this via ABAP calls from XSLT.2
Unfortunately, you can only view the messages output
via the xsl:message command when you use the XSLT
4.2 Integrating XSLT in ABAP
Tester or the XSLT Debugger.1
The debugger can also display the command line that This section describes how to call XSLT programs from
is currently executed, the document position, and the ABAP and alternatively, how to call ABAP from XSLT.
values of variables. Moreover, you can set breakpoints. We’ll use ABAP syntax as of Release 6.20 here. Lan-
guage constructions that are considered “obsolete” are
1 It is a general drawback of the XSLT specification that it
doesn’t describe where exactly the messages must be out-
put. Consequently, each XSLT processor has its own output 2 The xsl:message command is not very useful here. It often
method. Strictly speaking, the SAP implementation also con- makes more sense to store logging information in separate
tains ABAP classes that can be used to evaluate the messages elements in the XML output. You can find more useful infor-
that have been output; however, we don’t recommend that mation on test outputs and on debugging XSLT programs in
you use those classes. the XSLT Cookbook ( Sal Margano: O’Reilly 2005 ).
www.sap-press.com 31
4 XSL Transformations
still supported for reasons of downward compatibility, things, this parameter can be used for output formatting
however, they should no longer be used because there of XML documents.
are better options available. Not only did the upgrade
from Release 6.10 to 6.20 involve adding new concepts, Don’t forget exception handling!
but it also required the standardization of existing con- The CALL TRANSFORMATION command can trigger ex-
cepts. Developers should study these advanced develop- ceptions Since Release 6.40, the common basic class
ments so they can reduce the degree of complexity in the CX_TRANSFORMATION_ERROR, is available for XSLT
set of commands. programs and simple transformations ( see Chapter 5 ).
Even though the listings shown here don’t contain the
Calling XSLT from ABAP handling of system errors due to space limitations, this
You can call an XSLT program via the CALL TRANSFORMATION is an indispensable component of a robust and defen-
command. At this point, we only want to briefly describe sive kind of programming. You will note that especially
the general syntax of the call. For further details such as when transforming XML data into ABAP data, the as-
exception handling, you should refer to The Official ABAP signment of an alphanumeric value to a numeric ABAP
Reference ( Horst Keller: SAP PRESS 2004 ). data type, for instance, triggers an exception that must
CALL TRANSFORMATION transformation be handled.
[PARAMETERS parameters]
SOURCE source The following lines show the structure of the CATCH block
RESULT result. that contains a transformation error:
DATA: l_rif_ex TYPE REF TO
The transformation source can be specified both stati- cx_xslt_runtime_error,
cally and dynamically. You can transfer ABAP data objects l_var_text TYPE string,
to the transformation via PARAMETERS. Within the trans- l_var_source_line TYPE i,
formation, one of the following type specifications can l_var_program_name TYPE syrepid,
be used for the parameter: string, xstring, number, l_var_include_name TYPE syrepid.
boolean, object, or nodeset. The following section pro-
vides examples of how to transfer objects and use meth- CATCH cx_xslt_runtime_error INTO l_rif_ex.
ods. To transfer nodesets, you must use an object of the l_var_text = l_rif_ex->get_text( ).
if_ixml_node or if_ixml_collection type. This XML * Determine error position
library interface was described in detail in Chapter 3. CALL METHOD
Both the source and the result of a transformation con- l_rif_ex->get_source_position
sist of either ABAP data, which is available in the asXML IMPORTING
view in the transformation, or XML documents. source_line = l_var_source_line
The CALL TRANSFORMATION command enables you to program_name = l_var_program_name
transform ABAP data into ABAP data, XML documents include_name = l_var_include_name.
into XML documents, and ABAP data to XML and vice * Log error
versa. In the data source ( SOURCE parameter ) and tar- IF l_var_text IS NOT INITIAL.
get ( RESULT parameter ), XML documents are available as WRITE: / l_var_text.
string, xstrings, or as reference variables of one of the WRITE: / 'The error exists in line:',
following types: if_ixml_istream, if_ixml_ostream, l_var_source_line.
if_ixml_document, if_ixml_node. You can also trans- ENDIF.
fer ABAP data dynamically by using a variable of the type
ABAP_TRANS_RESBIND_TAB. Calling ABAP from XSLT
Since Release 6.40 the OPTIONS parameter is available To a certain extent, every XSLT processor supports exten-
for the CALL TRANSFORMATION command. Among other sion mechanisms. For example, in our case, we can call
ABAP methods and function modules from a transfor- Another useful way of applying the ABAP integration is
mation. In one application of ABAP integration, we will the creation of error lists and process tracing. The trans-
demonstrate how you can store error messages in a log- formation shown in Listing 4.1 processes an XML docu-
ging object. Another typical application is the transforma- ment recursively and logs the occurrence of A elements,
tion in the data exchange process that discovers—during including their position, in the source text.
the transformation of an XML document—that a system The example in Listing 4.1 clearly illustrates the func-
error has occurred, or that the data does not meet the tionality of an XSLT program. An XSLT program consists of
data quality requirements agreed upon. Once the trans- a set of templates that are defined via the xsl:template
formation has been analyzed and additional error-han- command. The match="A" attribute assigns a template
dling mechanisms have been initiated, the logged error rule to the above template. This rule states that the tem-
messages are collected in a main memory component. plate can be used for processing the A elements.
For this purpose we’ll define an object called Z_CL_ At each point in time, the XSLT processor processes
LOGGER that contains a save method including the nodes of a context. At the beginning of the process, the
three parameters, I_STRING, I_LINE, and I_COLUMN. This context contains only the document root. For each node,
object must possess another attribute that collects the the template rules are analyzed in order to find out which
data in an internal table in the main memory, as well as template is appropriate for the node. The identified tem-
another method for saving the messages, for example, in plate is then evaluated. If there is more than one template
the business application log. This object is transferred to that meets the requirements, the template that meets the
the PARAMETERS3 parameter of the CALL TRANSFORMATION requirements most precisely is used. In our case, it means
statement. that the first A element is found, and the context of the
The SAP-specific extensions, sap:external-function process is newly set with regard to the element found. To
and sap:call-external, enable you to integrate ABAP continue the required recursive search for A elements, we
in XSLT. At this point, you must understand that a com- use the xsl:apply-templates command. If no other ele-
bination of a procedural programming style in ABAP and ment is found, the process terminates.
a function-based style in XSLT often results in programs This type of processing is rather general, but not very
that can hardly be maintained. And yet the ABAP integra- efficient. Section 4.7 deals with this aspect of process-
tion is generally unavoidable, particularly with regard to ing.
database access. Other areas of application include the For the integration in ABAP log messages, we define
implementation of counters and the access to number an object using a save method. The instance is trans-
range objects. ferred to the transformation via PARAMETERS object =
l_rcl_log. The <xsl:param name="OBJECT" /> statement
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:sap="http://www.sap.com/sapxsl" version="1.0">
<xsl:param name="OBJECT" />
<xsl:template match="A">
<sap:call-external name="OBJECT" method="save">
<sap:callvalue param="I_STRING" select="'A found'" />
<sap:callvalue param="I_LINE" select="sap:line()" />
<sap:callvalue param="I_COLUMN" select="sap:column()" />
</sap:call-external>
<xsl:apply-templates select="*"/>
</xsl:template>
</xsl:transform>
www.sap-press.com 33
4 XSL Transformations
ensures that the parameter is published within the trans- Similarly, the syntax required for calling class methods
formation: is also described in the SAP Library. In addition, you
DATA l_rcl_log can call methods dynamically via the method attribute:
TYPE REF TO z_cl_logger. method="METHOD_{$index}".4 This procedure is very gen-
DATA l_var_input TYPE string. eral, but not robust if the index is encoded in the trans-
DATA l_var_output TYPE string. formation instead of being determined at runtime by an
ABAP object.
CREATE OBJECT l_rcl_log. Compared to the sap:call-external command
l_var_input = described earlier, the sap:external-function com-
`<R><Level1><A>a</A></Level1> mand has some advantages. This command can also be
<A>a</A></R>`. used in XPath expressions. Its syntax is more compact
because it corresponds to a function definition at the top
CALL TRANSFORMATION z_messages_log level5 of the XSLT program. However, the consequence
PARAMETERS object = l_rcl_log of that is that a function value must be returned either
SOURCE XML l_var_input as a RETURNING parameter or as an individual EXPORTING
RESULT XML l_var_output. parameter. Other EXPORTING parameters are ignored.
When you extend the Z_CL_LOGGER class by a prot()
A common source of error is that the value of the trans- method that returns a BOOLEAN function value, you can
ferred object is not capitalized in the xsl:param state- define the call of this method as a top-level element by
ment. The values that are transferred along with the using the sap:external-function command, as shown
transformation are translated into the corresponding in the XSLT program in Listing 4.2.
ABAP values. In this context, a nodeset is automatically When the call is carried out via the sap:external-
transformed into an object that is implemented by the function, the attribute determines whether the method
if_ixml_node or if_ixml_node_collection interface call is a constructor ( constructor ), a class method
respectively ( see Section 3.1 ). ( class ), or a method of the object ( instance ).
When transferring attributes using the sap:callvalue The call of the external function prv:prot corresponds
statement, you should determine whether you have to to the convention that the first function argument is the
convert the attributes into a string first; otherwise, a name of the externally called object. This convention is
nodeset may be transferred, which generally causes a commonly used in Java.
type error. If a conversion is impossible, an exception— At this point, you could find it disturbing that the log-
CX_XSLT_ABAP_CALL_ERROR—is triggered that must be ging object is still contained in the interface of the CALL
absorbed by the surrounding ABAP program. The same TRANSFORMATION call as well as in the xsl:param element
holds true when an object call generates an exception. of the transformation. We should therefore use the fac-
If the method contains return parameters, you can tory pattern now. We’ll extend the Z_CL_LOGGER class
bind those parameters to a variable by using the sap: by a static method, create(), that returns an instance of
callvariable command: The <sap:callvariable name= Z_CL_LOGGER. This method is called within a transfor-
"variable" param="E_STRING"/> command transfers the mation, and the created object is stored in a variable. The
value of the variable variable into the exporting param- logging method is then called via this variable. Listing 4.3
eter, E_STRING . Here, too, an implicit conversion process describes this process.
is carried out. If this is not the outcome that we want, we
can use the type attribute to specify a conversion that’s 4 The contents of the method attribute are an attribute value
described in the SAP Library. This conversion enables you template ( AVT ). The XSLT processor can use the AVT at run-
time to determine a value that is contained in curly brackets
to bind the return value to an XSLT variable. Please refer ( {} ). With the method attribute, the value is stored in the
to the SAP Library for further details such as handling $index variable.
5 Top-level elements are the child elements of xsl:transform
CHANGING parameters. and xsl:stylesheet.
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:sap="http://www.sap.com/sapxsl" xmlns:prv="urn:mine" version="1.0">
<xsl:param name="OBJECT" />
<sap:external-function name="prv:prot" method="prot" kind="instance" >
<sap:argument param="i_string"/>
<sap:argument param="i_line"/>
<sap:argument param="i_column" />
<sap:result param="e_return" type="boolean" />
</sap:external-function>
<xsl:template match="A">
<xsl:value-of select="prv:prot($OBJECT, 'A found', sap:line(), sap:column())"/>
<xsl:apply-templates select="A"/>
</xsl:template>
</xsl:transform>
In the example in Listing 4.3, the solution may not appear Instead, they can only call objects that encapsulate those
to be adequate; however, typically, it can be considered calls. This restriction, however, should not necessarily be
good programming to create objects via factory methods, regarded as a weakness as it exemplifies the efficiency of
to store references to those objects, and lastly, to access class-based exceptions in ABAP. If an error occurs in a
the objects outside of the transformation. deep software layer, it must be logged and then neutral-
The sap:external-function command does not sup- ized in the calling layer. If, for instance, an error occurs in
port optional parameters. Consequently, you must pro- an ABAP call from XSLT, because a data record is locked in
gram different sap:external-function commands for the database or doesn’t exist, often times the transforma-
different calls. tion is canceled, which, in turn, causes the calling ABAP
program to react.
Exception Handling in ABAP Calls from XSLT If there were only function modules available for that,
There are ABAP programmers who complain that it is we would have to forward the return codes and error
impossible to call function modules directly from XSLT. logs in an additional interface. The concept of class-based
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:sap="http://www.sap.com/sapxsl" xmlns:prv="urn:mine" version="1.0">
<sap:external-function name="prv:create" class="Z_CL_LOGGER" method="create" kind="class" >
<sap:result param="e_object" type="external" />
</sap:external-function>
<sap:external-function name="prv:prot" method="prot" kind="instance" >
<sap:argument param="i_string"/>
<sap:argument param="i_line"/>
<sap:argument param="i_column" />
<sap:result param="e_return" type="boolean" />
</sap:external-function>
<xsl:variable name="instance" select="prv:create()"/>
<xsl:template match="A">
<xsl:value-of select="prv:prot($instance, 'A found', sap:line(), sap:column())"/>
<xsl:apply-templates select="A"/>
</xsl:template>
</xsl:transform>
www.sap-press.com 35
4 XSL Transformations
www.sap-press.com 37
4 XSL Transformations
child elements of the ARTICLE_TO_CATALOGGROUP_MAP ele- In the transformation, we analyze all catalog items ( arti-
ment in order to find out if it is a starter, a main course, cles ). Those items are programmed using the BME:ARTICLE
or a dessert. This system is used to create an entry for the elements. For each catalog item, we call the CreateMeal
corresponding transparent table. template to create an entry for the SAP tables, SMEAL and
The XSLT program in Listing 4.4 performs exactly this SMEALT. In our example, a catalog item can be a starter,
transformation. a main course, and a dessert. Because each of those
At the beginning of the XSLT program in Listing 4.4, meals must be saved in different SAP tables ( SSTARTER,
we define a local namespace using the prefix BME because SMACOURSE, or SDESSERT ), we must first define the
a local namespace was defined in the original XML docu- types. To do that, we use the item name to determine
ment for the BME root element and, recursively, for its the associated ID catalog group via the ARTICLE_TO_
children using the following URI: http://www.bmecat. CATALOGGROUP_MAP element, for which we have defined a
org/XMLSchema/1.2/bmecat_new_catalog. key_article index to increase the system’s performance.
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:sap="http://www.sap.com/sapxsl" xmlns:asx="http://www.sap.com/abapxml"
xmlns:BME="http://www.bmecat.org/XMLSchema/1.2/bmecat_new_catalog"
exclude-result-prefixes="BME" version="1.0">
<xsl:param name="CARRID"/>
<xsl:strip-space elements="*"/>
<!-- Create key for fast access -->
<xsl:key match="BME:CATALOG_GROUP_ID" name="key_article" use="string(../BME:ART_ID)"/>
<xsl:template match="/">
<asx:abap>
<asx:values>
<xsl:for-each select="/BME:BMECAT/BME:T_NEW_CATALOG/BME:ARTICLE">
<xsl:variable name="article" select="."/>
<!-- Determine item number -->
<xsl:variable name="mealnumber" select="string(./BME:SUPPLIER_AID)"/>
<!-- Determine catalog grouping -->
<xsl:variable name="CatalogID"
select="string(key('key_article',$mealnumber))"/>
<!-- Create meal -->
<SMEAL>
<xsl:call-template name="CreateMeal">
<xsl:with-param name="mealnumber" select="$mealnumber"/>
<xsl:with-param name="article" select="$article"/>
</xsl:call-template>
</SMEAL>
<!-- Create long text for meal -->
<SMEALT>
<xsl:call-template name="CreateMealText">
<xsl:with-param name="mealnumber" select="$mealnumber"/>
<xsl:with-param name="article" select="$article"/>
</xsl:call-template>
</SMEALT>
<!-- Analyze meal type -->
<xsl:choose>
<xsl:when test="starts-with($CatalogID, 'DT1010')">
<SMACOURSE>
A Default namespace 46 H
Deployment descriptors 84
A2A integration 10 Head-body pattern 27
Deserialization 57
Abstract syntax trees 51 HL7 messages 5
Design pattern 26
asXML 36, 61, 105 Home interface 84
Displaying XML documents 104
asXML representation 36 HTTP requests 104
Diversifying development and testing
Attribute value template 34
105
Document type definitions 8 I
B DOM 15
ICF 104
DTD 17
Base64 37 if_ixml 14
bindingTemplate 85 if_ixml_attribute 13
BizTalk messages 5 E if_ixml_document 13, 15, 32
BMEcat 5, 107, 108 if_ixml_event 14, 24, 25
E-business standards 100
BMEcat catalog 37 if_ixml_istream 14, 32
ebXML 5, 99
businessEntity 85, 93 if_ixml_node 13, 27, 32, 34
eCl@ss 108
businessService 85 if_ixml_node_collection 34
EDIFACT 7, 8
if_ixml_node_filter 27
EJB 84
if_ixml_ostream 14, 32
EJB specification
C restrictions 84
if_ixml_parser 14, 19
if_ixml_renderer 17
CALL TRANSFORMATION 32, 37, 56 Encodings 14
if_ixml_stream 14
CDATA sections 25 Enterprise Application Integration 9, 99
if_ixml_stream_factory 14
Chained exceptions 36 Enterprise Application Project 90
if_serializable_object 10
Character sets 14, 52 Exceptions
Interface formats
CIF 5 Chained 36
Proprietary 101
CL_GUI_HTML_VIEWER 104
Internet Communication Framework (ICF)
CL_IXML 14
Code generation 11, 50
F 11
ISO-8859-1 14
Complex transformations 104 Factory pattern 34
ISO 4217 52
Content models function-available() 45
iXML library 13
Non-deterministic 61
current-group() 46 G
current-grouping-key() 46
Generic object services 104 J
cXML 5, 16, 59, 68, 69, 113
group-adjacent() 46 J2EE 11, 84
group-by() 46 J2EE connector architecture 84
D group-ending-with() 46 Java 54, 81
group-starting-with() 46 JAXP 81
Data integration 9
gXML 5 JAXP 1.3 97
Data quality 101
JCo 84
Datastore component 26
Default error handler 81
www.sap-press.com 119
Index
www.sap-press.com 121