In the second part of my weblog I am going to present some techniques used for XML processing. The focus of this issue is on basic conditional transformations in Simple Transformations.
Part 2 – Dealing with optional elements and attributes
XML is a generic tree model consisting of elements and attributes. This guarantees the generality and flexibility of this information model although some aspects are disturbing: for instance structured attributes aren’t supported.
Handling optional elements and attributes is part of your daily work in XML processing. I think it’s a good example to introduce some conditional constructs of Simple Transformations. Just imagine that you want process following example with an optional <B> element:
This is very easy to transform using the tt:cond statement. tt:cond is evaluated during serialization as well as deserialization. We consider only the case no prerequisites are formulated and the content of the tt:cond element is a pattern, i.e. a literal XML element, a non-literal attribute with content, not empty literal text or an explicitly empty template content. During serialization the element is considered if the content of the element is not empty. During deserialization the element is considered if the content matches with the input stream.
If you want to transform the XML document above you may use following code:
If there’s a <B> element in the input stream the tt:cond condition is evaluated and the value will be written to ROOT1.
You can test the transformation above with the following ABAP program:
The Simple Transformation can process the XML document above without the <B>element. The body of the tt:cond statement is a pattern that allows the ST processor can decide whether the condition is met or not. In this case the value is copied to ROOT1.
If the optional <B> element follows the <A> elements you can use following code where tt:loop will recognize when to stop:
But we have to be careful: during deserialization the ST processor must be able (especially in nested loops) to recognize when a loop ends. Later I will come back to that point.
Before you learn how to deal with optional attributes let me introduce the tt:attribute using a small example. We want to transform the values of attr1 and attr2:
We can do it with following transformation:
Here are some additional remarks concerning the transformation above:
- The order of the attributes doesn’t care.
- You can repeat an attribute more than once! The first value will be taken.
- Additional attributes (for example attr3, attr4 and so on) are skipped.
- You can define additional literal attributes. It doesn’t care in which order they occur during deserilization, but their name and content must be correct otherwise you get an exception CX_ST_MATCH_TEXT.
You can use tt:cond statement described above to make the first attribute optional:
Just consider the case you want to deserialize following XML document in the following way: the content of pairs of <A> and <B> elements should will be written into another ABAP variable.
Therefore you use following ABAP code:
Following transformation will trigger the exception CX_ST_MATCH_ELEMENT:
This isn’t strange. If you are familiar with W3C XML schema you will immediately remember the similarity to the so called ‘unique particle attribution rule’. When reading the last <A> element the ST processor doesn’t know which branch of the information model must be processed. Indeed the XML document above is a ‘nondeterministic content model’ that can’t be described with W3C XML schema.
In schema design it’s good style to use the so called collection pattern: just enclose your list with another element. This will make your schema and your XML documents easier to understand and avoids nondeterminism.
We learned about the tt:cond statement in its basic form and used it to process conditional elements and attributes. Optional elements following reptitions of elements can cause trouble that can be avoided when using deterministic content models especially the collection pattern.