I consistently run into trouble when using XSLT Transformation to import XML data into (deep) ABAP Structures. Partly because I do not use it often I guess. So to make sure that next time I will quickly find a how-to that works for me I created this blog
😉
Other options are; to use Simple Transformation or the standard
Identity Transformation (XSLT via existing transformation 'ID').
The goal now is to import the following XML into a deep ABAP structure using
XSLT
The XML
<?xml version="1.0" encoding="UTF-8"?>
<File>
<Head>
<Name>K. Richards</Name>
</Head>
<Items>
<ITM QTY="23" EAN="123123123123" CAT="BL"/>
<ITM QTY="100" EAN="123123123123" CAT=""/>
<ITM QTY="240" EAN="123123123123" CAT=""/>
<ITM QTY="989" EAN="123123123123" CAT=""/>
<ITM QTY="1000" EAN="123123123123" CAT=""/>
<ITM QTY="5" EAN="123123123123" CAT="BL"/>
<ITM QTY="50" SOH="4000299949" EAN="123123123123" SOI="000010" CAT=""/>
<ITM QTY="140" EAN="123123123123" CAT=""/>
<ITM QTY="420" EAN="123123123123" CAT="QI"/>
<ITM QTY="30" EAN="123123123123" CAT=""/>
<ITM QTY="20" EAN="123123123123" CAT="QI"/>
<ITM QTY="475" SOH="4000299949" EAN="123123123123" SOI="000040" CAT=""/>
<ITM QTY="300" EAN="123123123123" CAT=""/>
<ITM QTY="994" EAN="123123123123" CAT=""/>
<ITM QTY="24" EAN="123123123123" CAT="BL"/>
<ITM QTY="3" EAN="123123123123" CAT="BL"/>
<ITM QTY="441" EAN="123123123123" CAT=""/>
<ITM QTY="240" EAN="123123123123" CAT="QI"/>
<ITM QTY="5" EAN="123123123123" CAT=""/>
<ITM QTY="102" EAN="123123123123" CAT="BL"/>
<ITM QTY="2" EAN="123123123123" CAT=""/>
<ITM QTY="360" EAN="123123123123" CAT="QI"/>
<ITM QTY="403" EAN="123123123123" CAT=""/>
<ITM QTY="425" SOH="123123123123" EAN="6941023243415" SOI="000030" CAT=""/>
<ITM QTY="100" EAN="123123123123" CAT=""/>
<ITM QTY="220" EAN="123123123123" CAT=""/>
<ITM QTY="1000" EAN="123123123123" CAT=""/>
<ITM QTY="25" SOH="4000299949" EAN="123123123123" SOI="000020" CAT="BL"/>
<ITM QTY="425" SOH="4000299949" EAN="123123123123" SOI="000020" CAT=""/>
<ITM QTY="340" EAN="123123123123" CAT=""/>
<ITM QTY="1" EAN="123123123123" CAT="BL"/>
</Items>
</File>
The XSLT
The import can be achieved with the below XSL Transformation (Transaction STRANS)
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:sap="http://www.sap.com/sapxsl" version="1.0">
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<FILE> <!--FILE Needs to match name of RESULT variable in CALL TRANSFORMATION call-->
<xsl:for-each select="/File">
<!-- <DUMMY1> = Dummy, not in ABAP structure-->
<DUMMY1>
<HEAD>
<NAME>
<xsl:value-of select="Head/Name"/>
</NAME>
</HEAD>
<ITEMS>
<xsl:for-each select="Items/ITM">
<DUMMY2>
<!-- <DUMMY2> = Dummy, not in ABAP structure-->
<QTY>
<!-- @ = Attribute of element rather than element-->
<xsl:value-of select="@QTY"/>
</QTY>
<SOH>
<xsl:value-of select="@SOH"/>
</SOH>
<EAN>
<xsl:value-of select="@EAN"/>
</EAN>
<SOI>
<xsl:value-of select="@SOI"/>
</SOI>
<CAT>
<xsl:value-of select="@CAT"/>
</CAT>
</DUMMY2>
</xsl:for-each>
</ITEMS>
</DUMMY1>
</xsl:for-each>
</FILE>
</asx:values>
</asx:abap>
</xsl:template>
</xsl:transform>
The ABAP
And here is the ABAP Report that calls the transformation
REPORT zjbo_xslt_2.
TYPES BEGIN OF lty_items.
TYPES qty TYPE string.
TYPES soh TYPE string.
TYPES ean TYPE string.
TYPES soi TYPE string.
TYPES cat TYPE string.
TYPES END OF lty_items.
TYPES BEGIN OF lty_head.
TYPES name TYPE string.
TYPES END OF lty_head.
TYPES BEGIN OF lty_out.
TYPES head TYPE lty_head.
TYPES items TYPE STANDARD TABLE OF lty_items WITH DEFAULT KEY.
TYPES END OF lty_out.
DATA lv_xml TYPE string..
DATA lt_xml TYPE STANDARD TABLE OF string.
DATA ls_out TYPE lty_out.
DATA lt_out TYPE STANDARD TABLE OF lty_out.
PARAMETERS p_file TYPE string DEFAULT 'C:\link\to\test.xml'.
"Load xml file
cl_gui_frontend_services=>gui_upload(
EXPORTING
filename = p_file
filetype = 'ASC'
CHANGING
data_tab = lt_xml
EXCEPTIONS
OTHERS = 19 ).
lv_xml = concat_lines_of( lt_xml ).
CALL TRANSFORMATION zmy_xslt_2
SOURCE XML lv_xml
RESULT file = lt_out.
cl_demo_output=>new( )->write_data( lt_out[ 1 ]-head
)->write_data( lt_out[ 1 ]-items )->display( ).
Now for some pointers
Here are some important tips
- The RESULT variable of the CALL TRANSFORMATION must have the same name as the root target element in the XSLT (in this example; 'file' == <FILE>
- The target elements in the XSLT (ie the elemenst that correspond with your target ABAP structure) must be in CAPITALS; Like <HEAD>, <NAME>, ...
- The Source element references must be in same case as in the XML. Like "/Items/ITM"
- The output of the CALL TRANSFORMATION must be a table type (structure is not allowed, other outputs like XML and ref to data is also possible, for that see SAP Help). Like in our example; lt_out is a table type.
- Each substructure or table line in the output needs to be explicitly defined with a dummy structure name. These dummy structure names do not exist in the ABAP target, but need to be defined. The name used is irrelevant. See <DUMMY1> and <DUMMY2> in XSLT
UPDATE July 2019:
sandra.rossi wrote a follow up using ST Transformation instead of XSLT;
https://blogs.sap.com/2019/07/02/st-transformations-xml-2-abap-a-working-example/
Joris Bots