Technology Blogs by SAP
Learn how to extend and personalize SAP applications. Follow the SAP technology blog for insights into SAP BTP, ABAP, SAP Analytics Cloud, SAP HANA, and more.
cancel
Showing results for 
Search instead for 
Did you mean: 
gunther_stuhec
Advisor
Advisor
It is quite often the case to select the value from one specific source item out of two or more different source items depending on a boolean expression so that this value can be individually processed and accordingly written into mapped target node. For example, the source MIG has an “Amount” node which allows values based on different currencies and this amount must be converted to one target currency. Another example is a “Date Time Stamp” source node which follows different time zones, and this date time stamp must be converted into the only target time zone. In both examples are the code values (currency and time zone) responsible for the further processing into the appropriate target result. Especially this can be expressed by a conditional expression in form of an if-then-else statement. Another example is to write a temperature into the target node, if this is within a specific range of temperatures. This blog explains how you can use define a conditional expression using XSLT V2.0 xsl:choose, XPath X2.0 functions if ( … ) then … else … function or by the Integration Advisor specific qualifier approach which indirectly enable a conditional expression.


You are at Mapping Guidelines (MAG)



Comparison Expression and Operators


A conditional expression has one or more conditions with comparison or test expressions that return a boolean value true or false. Each expression compares one argument ($arg1) with another argument ($arg2) by using a comparison operator such as is equals to, it is less or greater than, etc. Each comparing argument can be a single value, a constant, a set of values, or a XPath functions which returns a single value or a set of value. Depending on the kind of arguments, you must use in XPath different representations of comparison operators. If you want to compare exactly one value with exactly one another value you can use the operators: eq, ne, lt, gt, le or ge. If you want to compare a single value with a sets of value, you should use the operators for general comparison: =, !=, < (alternatively: &lt;), > (alternatively: &gt;), >= (alternatively: &lt;=), or > (alternatively: &gt;=).

The following table lists you the different comparison operators and their behavior:


































































Name Operator Convention Example Comment
Is equals to = / eq General comparison:

  • $arg1 = $arg2


Value comparison:

  • $arg1 eq $arg2


General comparison:

  • Numeric: 20 = (10, 20, 30) → true

  • String: 'EUR' = ('EUR', 'GBP', 'IND') → true


Value comparison:

  • Numeric: 20 eq 10 → false

  • String: 'EUR' eq 'USD' → false


Is not equals to != / ne General comparison:

  • $arg1 != $arg2


Value comparison:

  • $arg1 ne $arg2


General comparison:

  • Numeric:
    10 != (10, 20, 30) → true
    recommended:
    not(10 = (10, 20, 30)) → false

  • String:
    'EUR' != ('EUR', 'GBP', 'IND') → true
    recommended:
    not('EUR' = ('EUR', 'GBP', 'IND')) → false


Value comparison:

  • Numeric: 20 ne 10 → true

  • String: ‘EUR' ne 'USD' → true


It is not recommended to use the != operator to compare inequality where one or both arguments are sets of values. It evaluates always to true when there is at ease one value is not equal. For this purpose it is recommended to use not( … ) such as not(10 = (10, 20, 30)) à false or not('EUR' != ('EUR', 'GBP', 'IND')) à false
Is less than  &lt; /  lt General comparison:

  • $arg1 &lt; $arg2


Value comparison:

  • $arg1 lt $arg2


General comparison:

  • Numeric:
    20 &lt; (10, 20, 30) → true

  • String:
    'EUR' &lt; ('EUR', 'GBP', 'IND') → false


Value comparison:

  • Numeric: 20 lt 10 → false

  • String: ‘EUR' lt 'USD' → true




The general comparison of numeric values returns a true, because the numeric value 20 is smaller than the highest numeric value of the set of values.

xPath also allows the use of "<", but masking within XSLT is required (&lt;)
Is greater than &gt; / gt General comparison:

  • $arg1 &gt; $arg2


Value comparison:

  • $arg1 gt $arg2


General comparison:

  • Numeric:
    20 &gt; (10, 20, 30) → true

  • String:
    'EUR' &gt; ('EUR', 'GBP', 'IND') → false


Value comparison:

  • Numeric: 20 gt 10 → true

  • String: ‘EUR' gt 'USD' → false




The general comparison of numeric values returns a true, because the numeric value 20 is higher than the smallest numeric value of the set of values.

xPath also allows the use of ">", but masking within XSLT is recommended (&gt;)
Is less than or equals to &lt;= / le General comparison:

  • $arg1 &lt;= $arg2


Value comparison:

  • $arg1 le $arg2


General comparison:

  • Numeric:
    20 &lt;= (10, 20, 30) → true

  • String:
    'EUR' &lt;= ('EUR', 'GBP', 'IND') → true


Value comparison:

  • Numeric: 20 le 10 → false

  • String: ‘EUR' le 'USD' → true


xPath also allows the use of "<=", but masking within XSLT is required (&lt;=).
Is greater than or equals to &gt;= / ge General comparison:

  • $arg1 &gt;= $arg2


Value comparison:

  • $arg1 ge $arg2


General comparison:

  • Numeric:
    20 &gt;= (10, 20, 30) → true

  • String:
    'EUR' &gt;= ('EUR', 'GBP', 'IND') → true


Value comparison:

Numeric: 20 ge 10 → true

String: ‘EUR' ge 'USD' → false
xPath also allows the use of "<=", but masking within XSLT is recommeded (&gt;=)
Has same identify (not same values) is

  • $node1 is $node2




$nodes_in/amount is $nodes_in/amount → true

$nodes_in/amount is $nodes_in/currency → false
“is” compares the identity of two nodes rather the values.
Returns the boolean value not( … )

  • not( $arg )


General comparison:

  • Numeric: not( 20 = (10, 20, 30 )) → false

  • String: not( 'EUR' = ('EUR', 'GBP', 'IND')) → false


Value comparison:

  • Numeric: not( 20 eq 10) → true

  • String: not( 'EUR' eq 'USD') → true


It returns the resulting boolean from true to false or vice versa. See also the use in is not equals for general comparison

If you want to create in Integration Advisor mapping functions with a general comparison it is recommended to just use the alternative operators: &lt, &gt;,&lt;= and &gt;, because all the mapping functions are expressed within XSLT elements.

It is not necessary to just use the in the test expressions comparison operations. You can also use all other XPath functions, which returns a boolean value, such as

  • empty($arg as item()*),

  • exists($arg as item()*),

  • contains($arg as string?, $arg2 as string?[, $collation as sting]?),

  • ends-with($arg as string?, $arg2 as string?[, $collation as sting]?),

  • matches($arg as string?, $pattern as string[, $collation as sting]?), or

  • starts-with($arg as string?, $arg2 as string?[, $collation as sting]?)


You’ll find more about it in the blog Integration Advisor – Mapping element functions for comparing nodes and values | SAP Blogs

Furthermore, you can write further complex functions as arguments that calculate boolean values.

Conditional Expression


In Integration Advisor, it is possible to do a conditional expression by the following optionss:

  • XSLT: xsl:choose …  xsl:when … xsl:otherwise …

  • XSLT: xsl:if

  • XPath: if ( … ) then … else …, or

  • Via qualified group or peer nodes


How to create these conditional expressions and their different behaviors can best be explained by an example use case. The requirement is to calculate the target amount in its target currency ‘EUR’ (Euro) from the source amount (Source node: $nodes_in/D_6345) by using the corresponding exchange rate of the specific source currency (Source node: $nodes_in/D_5004s). The supported currencies are CNY (Yuan Renminbi), GBP (Pound Sterling), INR (Indian Rupee) or USD (US Dollar).

Xsl:choose … xsl:when … xsl:otherwise …


The xsl:choose has a per different condition a xsl:when element. The attribute @test of the xsl:when element provides the comparison expression. The xsl:choose may have a xsl:otherwise element, which indicates the else state to be taken if none of the other xsl:when choices matches. xsl:choice, is useful, if you want to involve creating complex and deep XML structures in the processing. But this is quite seldom the case, because the mapping elements in MAGs are just focusing on value of leaf-nodes.

Convention:
<xsl:choose>
(<xsl:when test="$arg1">
$arg2
</xsl:when>)* <!-- Repeadable-->
<xsl:otherwise>
$arg3
</xsl:otherwise>
</xsl:choose>

 

Arguments

  • $arg1 in attribute @test must have a XPath comparison expression as described in chapter “comparison expression and operators”. This comparison expression must result with a boolean value true or false.

  • $arg2 is the resulting argument that will be taken when the comparison expression in $arg1 matches. This resulting argument could be either a simple constant, a node selection or further processing and calculation instructions.

  • $arg3 is the resulting in xsl:otherwise, if there is no match with the comparison expressions in all declared xsl:when elements.


In the following Integration Advisor mapping function example each xsl:when tests, if the node $nodes_in/D_6345 has a specific currency code. For better readability this currency code is set into a variable $vCry and the amount is set into the variable $vAmt.

If a currency code in $vCry matches to a specific xsl:when statement, the corresponding function in xsl:value-of will be taken for calculating the output amount by multiplying the input value from variable $vAmt with the specific currency ratio. The function format-number converts the output into a numeric format with two digits. All non-listed currency codes will be covered by the element xsl:otherwise, which generates an error.


Figure 1: Conditional expression by xsl:choose


If you like, you can use xsl:sequence or xsl:copy-of instead of xsl:value-of. The different behaviour is described in blog Integration Advisor – Mapping element functions, the use of xsl:copy, xsl:copy-of, xsl:sequence, or ...

Example input values, function and output:













Input (Example) Mapping Function Output (Example)


(1) D_5004: 112,23

(2) D_6345: ‘CNY’

<xsl:variable name="vAmt" select="$nodes_in/D_5004"/>
<xsl:variable name="vCry" select="$nodes_in/D_6345"/>
<xsl:choose>
<xsl:when test="$vCry = 'CNY'">
<xsl:value-of select="format-number($vAmt * 0.12823,'#.00')"/>
</xsl:when>
<xsl:when test="$vCry = 'GBP'">
<xsl:value-of select="format-number($vAmt * 1.15349,'#.00')"/>
</xsl:when>
<xsl:when test="$vCry = 'INR'">
<xsl:value-of select="format-number($vAmt * 0.01120,'#.00')"/>
</xsl:when>
<xsl:when test="$vCry = 'USD'">
<xsl:value-of select="format-number($vAmt * 0.84015,'#.00')"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="error(QName( (),
'D_6345' ), concat('Currency ''', $vCry, ''' in D_6345 is not supported'))"/>
</xsl:otherwise>
</xsl:choose>

(1) CONTENT: 14.39

xsl:if


The XSLT function xsl:if represents a conditional test against the input content. It is in other words a if-then-else statement without the else. Similar like xsl:choice, xsl:if is useful, if you want to involve creating complex and deep XML structures in the processing. But as I said this is quite seldom the case in context of the mapping elements in MAGs.

Convention:
<xsl:if test="$arg1">
$arg2
</xsl:if>

Arguments:

  • $arg1 in attribute @test must have a XPath comparison expression as described in chapter “comparison expression and operators”. This comparison expression must result with a boolean value true or false.

  • $arg2 is the resulting argument that will be taken when the comparison expression in $arg1 matches. This resulting argument could be either a simple constant, a node selection or further processing and calculation instructions.


The following mapping example shows the use of xsl:if. The mapping function has two different xsl:if statements. The first xsl:if matches if the occurrences of ID is lower or equal as 2 and the second xsl:if matches, if the occurrences of ID is greater than 2. The occurences of ID (D_1154) is stored in variable $vCount. The first xsl:if returns the last ID and the second xsl:if returns a concatenated string of the last value of Type (D_1156) and Version (D_4000)


Figure 2: Conditional expression by xsl:if


Example input values, function and output:













Input (Example) Mapping Function Output (Example)


(1) ID (D_1154): ABC-332022-002

(3) Type (D_1156): SALES

(3) Version (D_4000): 3.0

<xsl:variable name="vID" select="$nodes_in/ID"/>
<xsl:variable name="vType" select="$nodes_in/Type"/>
<xsl:variable name="vVer" select="$nodes_in/Version"/>
<xsl:variable name="vCount" select="count($nodes_in/ID)"/>
<xsl:if test="$vCount le 2">
<xsl:value-of select="$vID[$vCount]"/>
</xsl:if>
<xsl:if test="$vCount gt 2">
<xsl:value-of select="concat($vType[$vCount], '-', $vVer[$vCount])"/>
</xsl:if>

(1) CONTENT: 14.39

if ( … ) then … else …


xsl:choose and xsl:if are not a very elegant way to express a conditional expression. Since XPath 2.0 it is also possible to do the logic of conditional expression in a XPath expression itself by using if ( … ) then … else …. . It is useful in context the MAG related mapping elements, because the processing does not quite often involve creating complex and deep XML structures. The focus is almost on source and target values from leaf nodes.

Convention:
<xsl:sequence|xsl:value-of value="if ( $arg1 ) then $arg2 else $arg3"/>

The if( … ) then … else … can be expressed within a xsl:sequence or xsl:value-of

Arguments:

  • $arg1 must be in rounded brackets and must have XPath comparison expression similar like the attribute @test in xsl:when.

  • $arg2 is the resulting argument that will be taken when the comparison expression in $arg1 matches.

  • $arg3 is covers the resulting argument when the comparison expression in $arg1 does not match. In comparison with xsl:otherwise the else condition must have an argument. It could be at least an empty constant: ‘’.


As you can see in the following Integration Advisor mapping function example the different conditions of currency codes can be expressed by a nesting of the if( … ) then … else … expression.


Figure 3: Conditional expression by if( … ) then … else …


Example input values, function and output:













Input (Example) Mapping Function Output (Example)


(1) D_5004: 112,23

(2) D_6345: ‘CNY’

<xsl:variable name="vAmt" select="$nodes_in/D_5004"/>
<xsl:variable name="vCry" select="$nodes_in/D_6345"/>
<xsl:value-of select="if( $vCry = 'CNY' ) then format-number($vAmt * 0.12823,'#.00') else
if( $vCry = 'GBP' ) then format-number($vAmt * 1.15349,'#.00') else
if( $vCry = 'INR' ) then format-number($vAmt * 0.01120,'#.00') else
if( $vCry = 'USD' ) then format-number($vAmt * 0.84015,'#.00') else error(QName( (),
'D_6345' ), concat('Currency ''', $vCry, ''' in D_6345 is not supported'))"/>

(1) CONTENT: 14.39

Qualified References


The Integration Advisor provides a further elegant way for conditional expression, especially if one of the comparing arguments is a constant which can be expressed as a qualifier value. For this case it is useful to set for each condition a qualified node because all created qualified node based on same node will be considered as choices and will implicitly work similar like a comparison expression. This approach further reduces the amount of coding and increases the readability for business users. It requires a definition of qualified nodes per condition in the source MIG, the duplicates of nodes in a target MIG and the mapping elements between the corresponding nodes in the MAG.

The following figure shows how the different conditions for each currency can be expressed by qualified peer nodes in the source MIG. The blog Integration Advisor – The precision of semantics – Use of qualifiers | SAP Blogs describes how you can set these qualified nodes.


Figure 4: Qualified nodes per currency in source MIG


This approach requires duplicates of the same number of qualified nodes in the target MIG. However, since the Integration Advisor does not provide the duplicate node feature a workaround must be used for the creation of these duplicates. You’ll find this workaround in the blog ###BLOG###. The target MIG should look like the following figure.


Figure 5: Duplicated nodes in target MIG


Based on this source and target MIG it is now very easy to create the mapping elements between these prepared source and target nodes. Like in the following figure shown, each currency specific condition has a 1:1 mapping.


Figure 6: Use of qualified nodes as conditional expressions


The complexity of the function is significantely reduced and just cover the rule for conversion and the transformation into the target decimal format:













Input (Example) Mapping Function Output (Example)


(1) D_5004: 112,23

(2) D_6345: ‘CNY’

<xsl:value-of select="format-number($nodes_in/D_5004 * 0.12823,'#.00')"/>

(1) CONTENT: 14.39

The else condition in where the remaining code values should throw an error can be defined as following:









Mapping Function

<xsl:sequence select="error(QName( (),
'D_6345' ), concat('Currency ''', $nodes_in/D_6345, ''' in D_6345 is not supported'))"/>


The only reason, why the source node D_6345 is also mapped is that the currency code will be shown in the thrown error text, if this condition will take place in runtime.

Summary


Now you learned three different options for defining conditional expressions in a mapping guideline. How have now the choice. I personally prefer the use of the XPath if( … ) then … else …, if I have to create complex conditional expression in where especially the comparison expression needs more complex calculations and not just the comparison of constants. In case of comparing constants, I’m using the qualified references, if it is possible. Because this reduces the complexity of mapping functions, increases the human readability, and especially increases the efficiency. How? For example, in the case if you have a source MIG which might have many different conditions with different values which will be differentiated by constant values and this source MIG must be mapped to many target MIGs. It is than easier to explicitly express each condition by qualified nodes and focus on the just the necessary conversion rule between the mapped peer instead writing very complex and nested functions per MAG. It also reduces the maintenance efforts, if you must regularly update the source MIG with new constant values and further data dependent on these constants.

Further Reading


Read the following blog posts for more information related to the MAG editor and the functions:
5 Comments