[转]
Part 1 - Expressiveness of Simple Transformations

Simple Transformations are a SAP proprietary programming language that is integrated into ABAP by CALL TRANSFORMATION in kernel release 6.40. Its concept differs from other transformation languages, like JiBX, which is used for XML-Java mapping, or languages suitable both for queries and transformations, like Lore, XCerpt, XDuce or even XSLT, which is also supported in ABAP by CALL TRANSFORMATION. By looking at examples of ABAP package SST_DEMO you will understand how ST works. In contrast to XSLT, Simple Transformations (ST) are fast, memory efficient and symmetric, but lack of expressiveness.

Unfortunately I can't describe the power of ST in a mathematical way because, as usual, conditions cause most technical problems and the <tt:cond> seems to be difficult to handle. In fact, despite its name, Simple Transformations have very powerful and sometimes complicated commands.

So, when I'm asked about expressiveness, usually I tell how many times an ABAP or XML node can be accessed, mention the linear order during processing, lookahead of 1 and so on. If I start to tell about the possibilities to use parameters and breaking symmetry between serilization and deserilization, clever people will start to think how far they can go. A typical question is:

Can I create relational data models from nested structures with an unbounded number of occurrences during deserialization?

This is a natural question when you are doing data exchange with non-SAP systems using standardized XML frameworks and you want to save your data in transparent tables with additional foreign keys. If you are working with small datasets you won't have problems when you copy nested internal tables into the target data structure in ABAP. But let's ask the question if we can avoid heavy postprocessing. Of course, I would accept a pragmatic solution. Simple post processing in ABAP without copying data from one internal table into another would be acceptable.

The answer to the question above is, "no chance. You have to do heavy post processing." The reason is very simple and has to do with the <tt:loop> statement. Let's go into detail. In the following we consider an XML-document with a simple nested structure:

<A>
<name>A1</name>
<ZLS>
<Z>01</Z>
<Z>02</Z>
</ZLS>
</A>
<A>
<name>A2</name>
<ZLS>
<Z>03</Z>
</ZLS>
</A>

A typical example for a ST is to transform this XML document into an internal table whose table line contains an component 'nummer' and another internal table:

<?sap.transform simple?>
<tt:transform template="temp1"
xmlns:tt="http://www.sap.com/transformation-templates">
<tt:root name="ROOT"/>
<tt:template name="temp1">
<tt:loop ref=".ROOT" name="a">
<A>
<name>
<tt:value ref="$a.name" />
</name>
<ZLS>
<tt:loop ref="$a.zls" name="z">
<Z>
<tt:value ref="$z.nummer" />
</Z>
</tt:loop>
</ZLS>
</A>
</tt:loop>
</tt:template>
</tt:transform>

Note that the transformation above is symmetric and can be used in both directions to serialize and deserialize.

If we want to transform the XML stream above to a relational data model first we have to break up the nested structure. The values of <A> elements have to be put into one internal table and then <Z> elements into another one. Afterwards we have to deal with the problem of how to link these internal tables. Without ABAP calls from ST we will have problems generating the foreign keys we need. But perhaps this could be done using clever mapping methods. If there is a new <A> element we write additional information to the <Z> elements. Think of '+' respective of '-' in an alternating order each time a new <A> occurs. Later we could calculate foreign keys in a post processing step in ABAP. The result after the transformation would be as follows:

Internal table for <A> elements:

Counter calculated afterwards Value of element <name>
  A1
  A2

Internal table for <Z> elements:

Additional mark Value of element <Z>
+ 01
+ 02
- 03

Now we can do two loops in ABAP. At first we increment the counter for our <A> elements and then introduce a counter for our <Z> elements that is incremented each time our mark changes from '+' to '-' or vice versa. We would yield the following result which is exactly what we are looking for:

Internal table for <A> elements:

Counter during postprocessing Value of element <name>
1 A1
2 A2

Internal table for <Z> elements:

Additional mark after postprocessing Value of element <Z>
1 01
1 02
2 03

So let's start to code. The following transformation does this job without calculating alternating marks. Just have a look at the inner loop. We change the root from ROOT1 to ROOT2:

<?sap.transform simple?>
<tt:transform template="temp1"
xmlns:tt="http://www.sap.com/transformation-templates">
<tt:root name="ROOT1"/>
<tt:root name="ROOT2"/>
<tt:template name="temp1">
<tt:loop ref=".ROOT1" name="a">
<A>
<name>
<tt:value ref="$a.name"/>
</name>
<ZLS>
<tt:loop ref=".ROOT2" name="z">
<Z>
<tt:value ref="$z.nummer" />
</Z>
</tt:loop>
</ZLS>
</A>
</tt:loop>
</tt:template>
</tt:transform>

Then we test it with following quick-hack:

  DATA xml_string TYPE string.
data: begin of z,
mark type c,
nummer type string,
end of z.
data: begin of a,
counter type i,
name type string,
zl like table of z,
end of a.
data t_a like table of a.
data t_z like table of z.
xml_string = `<A>` &
`<name>A1</name>` &
`<ZLS>` &
`<Z>01</Z>` &
`<Z>02</Z>` &
`</ZLS>` &
`</A>` &
`<A>` &
`<name>A2</name>` &
`<ZLS>` &
`<Z>03</Z>` &
`</ZLS>` &
`</A>`.
CALL TRANSFORMATION my_first
SOURCE XML xml_string
RESULT ROOT1 = t_a
ROOT2 = t_z.

The result is annoying. The internal table t_a contains data of two <A> elements but t_z had only one entry with value "03".

The explanation is simple. When you want to deal with internal tables you have to use <tt:loop> statements. But everytime the <tt:loop> inner statement is called during deserialization the internal table is cleared, so in fact you are losing information in the example above. At first this example may look strange, just do the transformation back and look at the result, it will differ from the XML-document above! At first glance we have an asymmetric behaviour although we didn't use any asymmetric commands. At first I thought of it as a bug but switching the root makes sense. Why should ST inventors forbid those mechanisms and reduce expressivenes of this language?

In the following I want to mention a second aspect that seems to be confusing when you are confronted with ST for the first time.

You can assign the value of an element during deserilization only once!

In the rest of this issue we try to solve following task -- we want to deserialize the content of the <name> elements into one table and the nested <Z> elements into another if the content of its associated <name> element has value "A1". Perhaps you would start to define a variable <tt:variable name="N"/> for this task that stores the value of the current <A> element. I guess your code might look something like the following:

<?sap.transform simple?>
<tt:transform template="temp1"
xmlns:tt="http://www.sap.com/transformation-templates">
<tt:root name="ROOT1"/>
<tt:root name="ROOT2"/>
<tt:variable name="N"/>
<tt:template name="temp1">
<tt:loop ref=".ROOT1" name="a">
<A>
<name>
<tt:value ref="$a.name"/>
<tt:read type="C" var="N"/>
</name>
<tt:switch-var>
<tt:cond-var check="var(N)=C('A1')">
<ZLS>
<tt:loop ref=".ROOT2" name="z">
<Z>
<tt:value ref="$z.nummer" />
</Z>
</tt:loop>
</ZLS>
</tt:cond-var>
<tt:cond-var>
<tt:skip name="ZLS" count="1"/>
</tt:cond-var>
</tt:switch-var>
</A>
</tt:loop>
</tt:template>
</tt:transform>

If you run this transformation you won't get the expected result. Why? Compared to XSLT, variables in ST behave like variables in any other procedural language and you can assign them for more than one time. But following two lines doesn't work:

            <tt:value ref="$a.name"/>
<tt:read type="C" var="N"/>

First you want to read it into an ABAP structure and then bind it to a variable. Even changing the order of the two commands wouldn't help you. Let's test it with an easier example:

<?sap.transform simple?>
<tt:transform template="temp1"
xmlns:tt="http://www.sap.com/transformation-templates">
<tt:root name="ROOT1"/>
<tt:root name="ROOT2"/>
<tt:template name="temp1">
<X1>
<tt:value ref="ROOT1" />
<tt:value ref="ROOT2" />
</X1>
</tt:template>
</tt:transform>

Here is the ABAP code for running this ST:

  DATA xml_string TYPE string.
DATA field1 TYPE string.
DATA field2 TYPE string.
xml_string = `<X1> Test </X1>`.
CALL TRANSFORMATION my_transformation
SOURCE XML xml_string
RESULT ROOT1 = field1
ROOT2 = field2.

You will verify that ROOT2 is empty afterwards, so this doesn't work. Therefore we have to find another solution to implement our transformation, perhaps using the condition construct. But here we have another problem; the template content of the conditional is either a template (then you can't do assignments to variables for example) or it is evaluated unconditionally during deserialization. So, in fact, I can't tell you whether this will lead to success.

Summary
So let's summarize what we have learned. Programming ST is not difficult and ST does a great job transforming an XML document into nested ABAP structures, back and forth, because it is designed for this task. So to be honest, it's not surprising that transformations to a relational model is impossible without heavy post processing because for this task we have to create a set of internal tables from an XML tree and have to add foreign keys. In our small example above those keys are not part of our model so we would have to generate them and, of course, break the symmetry of our transformation thereby. The impossibility is caused by the fact that we can't increment variables and we can't append deserialized data to an internal table.

If we want to describe the (lack of) power of Simple Transformations I suggest to collect some simple examples for transformations we can't realize with ST and reduce other problems to them.

But does the lack of expressiveness really bother you? I don't believe in solutions that can solve every problem without causing new problems. Perhaps some new features that could help us will be added to ST in post 6.40 development but designers will have to be careful not to make the language too complex.

On the other hand, a software developer should try to choose the right technology -- iXML, XSLT, XSLT with ABAP calls or Java enhancement, ST or even JAXB -- and not to misuse a certain technology to create programs that can solve a problem in an unexpected way but are hard to understand and possibly difficult to maintain.

Check back soon for part 2 of this series!

ABAP xml的更多相关文章

  1. ABAP下载xml文件

    [转http://www.cnblogs.com/byfhd/archive/2007/08/17/859829.html] ************************************* ...

  2. ABAP的Package interface, 安卓的manifest.xml和Kubernetes的Capabilities

    ABAP 事务码SE21创建ABAP包接口.这是ABAP基于包层面的访问控制实现逻辑.包里可以存储很多ABAP对象.如果开发人员想将某些对象声明为包外程序也能访问,可以将这些对象放在包接口的Visib ...

  3. 20170319 ABAP 生成XML文件

    方法一:ABAP 使用method方式操作XML 转自:http://www.cnblogs.com/jiangzhengjun/p/4265595.html 方法二:STRANS 转换工具;使用st ...

  4. ABAP和XML数据格式互相转换的两种方式

    ABAP和XML数据格式互相转换是广大开发人员经常遇到的需求.本文介绍两种方式. 1. ABAP提供了一个工具类cl_proxy_xml_transform,通过它的两个方法abap_to_xml_x ...

  5. 【ABAP系列】SAP ABAP解析XML的示例程序

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[ABAP系列]SAP ABAP解析XML的示例 ...

  6. [SAP ABAP开发技术总结]ABAP读写、解析XML文件

    声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...

  7. ABAP术语-XML

    XML 原文:http://www.cnblogs.com/qiangsheng/archive/2008/03/21/1115743.html The "eXtensible Markup ...

  8. ABAP内表数据做层次XML输出

      *&---------------------------------------------------------------------**& Report  Z_BARRY ...

  9. ABAP 内表与XML转换

    1需求说明 在系统交互中需要将SAP内表转换为XML文件,发送给其他系统,并且将其他系统返回的XML文件转换为SAP内表. 2创建转换编辑器 事务代码:STRANS 选择简单转换 以图形方式编辑 右键 ...

随机推荐

  1. sed `grep` 查找并替换

    sed "s/libletvwatermark/libletv_watermark/" `grep -rl libletvwatermark` grep [options] 3.主 ...

  2. ABP框架EF6链接Oracle数据库手动迁移

    环境:VS2017 + ABP官方模板(不含Zero) +Oracle 11Gx64DB  + Oracle 11Gx32Client(PLSQL工具访问) 一.Abp项目的下载以及运行 1.创建ab ...

  3. ar命令提取.o的时候报错:is a fat file (use libtool(1) or lipo(1) and ar(1) on it)

    在解压.a文件的时候,报错:s a fat file (use libtool(1) or lipo(1) and ar(1) on it),原因是该.a文件包含了多个cpu架构,比如armv7,ar ...

  4. WebStorm初次使用

    1. ctrl + / : 单行注释2. ctrl + shift + / : 块注释 3:展开当前函数代码:Ctrl+“+”,收起当前代码:Ctrl+“-” 4:全局查找: Ctrl+Shift+F ...

  5. appium 学习和环境搭建

    官方网站: http://appium.io/ 1.安装各大开发环境:Nodejs. python .java 和 android 环境,并且配置环境变量. ✔ The Node.js binary ...

  6. docker与虚拟化的联系与区别

    虚拟化技术是一个总称,是一系列实现虚拟技术的统称.从广义上来说,虚拟化技术包括了虚拟机技术和容器技术, 所谓虚拟化技术最大的特点就是将一个真实的机器进行虚拟地分割,然后分割出来的部分可以独立使用   ...

  7. STM32 寄存器库和固件库

    寄存器和固件库开发的差别和联系 固件库就是函数的集合,固件库函数的作用是向下负责与寄存器直接打交道.向上提供用户函数调用的接口(API). 在 51 的开发中我们经常的作法是直接操作寄存器,比方要控制 ...

  8. Atitit..jdk java 各版本新特性 1.0 1.1 1.2 1.3 1.4 1.5(5.0) 1.6(6.0) 7.0 8.0 9.0 attilax 大总结

    Atitit..jdk java 各版本新特性 1.0 1.1 1.2 1.3 1.4 1.5(5.0) 1.6(6.0) 7.0 8.0 9.0 attilax 大总结 1.1. Java的编年史2 ...

  9. 查看系统启动内核检測硬件信息dmesg

    dmesg用来显示开机信息.kernel会将开机信息存储在ring buffer中.您若是开机时来不及查看信息,可利用dmesg来查看.开机信息亦保存在/var/log文件夹中.名称为dmesg的文件 ...

  10. (1)安装kvm

    我的环境是redhat虚拟机,版本信息如下: [root@localhost ~]# cat /etc/issue Red Hat Enterprise Linux Server release 6. ...