Copyright 2022 - BV TallVision IT

The simple XML transformation can be used to process a table in a table, but to do this, a little preparation in the definitions of these tables is required. No big deal, fantastic effect.

You want to put a list of sales orders into an XML file. Each order has a header and items, so we are composing the following (super simplified) XML output:

<SALESORDERS>
  <SALESORDER>
    <NUMBER>5105600117</NUMBER>
    <CUSTOMER>1615</CUSTOMER>
    <DATE>20170920</DATE>
    <ORDERLINES>
	  <ORDERLINE>
	    <MATERIAL>13-BIKE</MATERIAL>
            <AMOUNT>22</AMOUNT>
	  </ORDERLINE>
	  <ORDERLINE>
	    <MATERIAL>66734543BIKERACK</MATERIAL>
            <AMOUNT>2</AMOUNT>
	  </ORDERLINE>
    </ORDERLINES>
  </SALESORDER>
</SALESORDERS>

This XML file holds a series of sales orders and each sales order can have multiple orderlines. Let's assume we have selected/prepared 2 internal tables, GT_VBAK and GT_VBAP which hold the sales order information. First of all, note that table-in-table output can be processed in a transformation - if it is defined as a table in a table. Thus the GT_VBAK / GT_VBAP information should be merged into a single table - like so:

data: gt_vbak type STANDARD TABLE OF vbak,
      gt_vbap type STANDARD TABLE OF vbap.

* Fetch some example data
select * from vbak into table gt_vbak
  up to 10 rows.
select * from vbap into table gt_vbap
  for all entries in gt_vbak
  where vbeln = gt_vbak-vbeln.

types: ty_vbap_tab type SORTED TABLE OF vbap WITH UNIQUE KEY posnr,
       begin of ty_salesorder,
         vbak type vbak,
         vbap type ty_vbap_tab,
       end of ty_salesorder.
data: gt_salesorders type standard table of ty_salesorder,
      gw_salesorder type ty_salesorder,
      gw_vbak type vbak,
      gw_vbap type vbap,
      gv_xml_result type string.
* Merge the information into a single table / with tables
clear: gt_salesorders[].
loop at gt_vbak into gw_vbak.
  clear: gw_salesorder, gw_salesorder-vbap[].
  gw_salesorder-vbak = gw_vbak.
  loop at gt_vbap into gw_vbap
    where vbeln = gw_vbak-vbeln.
    append gw_vbap to gw_salesorder-vbap.
  endloop.
  append gw_salesorder to gt_salesorders.
endloop.

* Call the transformation
CALL TRANSFORMATION zsalesorders
  SOURCE
    gt_salesorders = gt_salesorders
  RESULT XML
    gv_xml_result. 

The zsalesorders transformation has type "Simple transformation" and looks like this:

<?sap.transform simple?>
<tt:transform xmlns:tt="http://www.sap.com/transformation-templates">

<tt:root name="ROOT"/>
<tt:root name="GT_SALESORDERS"/>

<tt:template>
<SALESORDERS>
<tt:loop ref=".GT_SALESORDERS" name="salesorder">
  <SALESORDER>
    <NUMBER><tt:value ref="$salesorder.VBAK.VBELN"/></NUMBER>
    <CUSTOMER><tt:value ref="$salesorder.VBAK.KUNNR"/></CUSTOMER>
    <DATE><tt:value ref="$salesorder.VBAK.ERDAT"/></DATE>
    <ORDERLINES>
    <tt:loop ref="$salesorder.VBAP" name="orderitem">
    <ORDERLINE>
      <MATERIAL><tt:value ref="$orderitem.MATNR"/></MATERIAL>
      <AMOUNT><tt:value ref="$orderitem.KWMENG"/></AMOUNT>
    </ORDERLINE>
    </tt:loop>
    </ORDERLINES>
  </SALESORDER>
</tt:loop>
</SALESORDERS>
</tt:template>

</tt:transform>

Note the nested loop, which is only allowed if the second loop is based on the data from the first loop. The concept can be repeated, even with table in table in table.