For Each

You can use the For Each transform to iterate over one input array element, which can be either a simple type or a complex type repeating structure, and set the value of an output element.

Overview

The For Each transform contains a nested map. You must map the elements in the nested map, otherwise no action is executed when the transform runs.

You can configure the For Each transform to run when there are input elements that match your input selection criteria.

You can configure the For Each transform to execute once when the input array is empty by setting the Allow Empty input condition in the Filter Inputs property tab.

You can specify the indexes of the input array that participate in the For Each operation by setting the Cardinality property.

You can specify an XPath condition over the indexes that participate in the For Each operation by setting the Filter Inputs property. This condition determines which indexes are applied.

Note: The XPath condition is tested against each instance of the input array, after you apply the Cardinality property.

Inputs

You can define multiple inputs to a For Each transform.
  • The For Each transform can have only one primary input connection, and the input must be repeatable.
    • The Graphical Data Mapping editor counts the indexes from 1 to N for each processed input.
    • When the input array element is empty or no inputs match a provided filter condition, the Graphical Data Mapping editor sets the index variable to 0.
    • The Graphical Data Mapping editor provides a variable that contains the index value of each iteration of the For Each transform. The name is as follows: $VarName-index, where VarName is the name of the repeating element.
      Note: Always use content assist to get the element name assigned by the Graphical Data Mapping editor to the repeating element.

      This figure shows the variable-index element.

  • Extra connections to the For Each transform must be of type Supplement. You can use these inputs in any of the following ways:
    • You might want to create a Filter Inputs expression based on the value of the input. You can use it to determine which indexes to apply as part of the transformation.

      This figure shows the For Each transform.

    • You might want to pass an extra element into the nested transform. This input is available in the mapping of each iteration that is run by the For Each transform.

      This figure shows the For Each transform.

  • You can configure the Cardinality property page on the For Each transform to indicate which index of an input array to iterate over.
  • You can configure the Filter Inputs property page to specify the matching criteria for filtering input repeating elements.

Cardinality

The Cardinality property determines the inputs that participate in the For Each operation.

The first index element is 1.

You configure the Cardinality tab in the Properties view to specify the indexes that are processed by the transform. For more information, see Selecting the indexes of input array elements.

This figure shows the Cardinality tab of the For Each transform properties.

Filter Inputs

Configure the Filter Inputs property tab to specify an XPath expression that determines which instances of the repeating input are processed in the nested mapping. Each element of the repeatable input is tested against the condition. The transform runs for those elements that satisfy the condition.

Note: The XPath condition is tested against each instance of the input array, after the Cardinality property is applied.

You can use XPath, or methods from Java™ classes to define the Filter Inputs expression. You can also create a complex expression comprising XPath and Java.

You can use context assist by pressing Ctrl+Space while you construct the Filter Inputs expression. For more information, see Using content assist (Mapping syntax).

Note: To obtain the exact name of the variables that are associated with the inputs, use content assist.

Enable Allow Empty input when the input array element is empty or no inputs match a provided filter condition, so that the transform is still entered exactly once. In this case, the primary input in the nested transform is missing, and the index variable is zero.

This figure shows the For Each transform.

Outputs

The output element of a For Each transform can be a simple element, or a complex element, that can be a repeating element or a non-repeating element.

The output array size is equal to the input array size, minus any elements that are filtered out after applying the Cardinality and the Filter Inputs properties.

Variable $VarName-index

In the For Each transform, you can use the $VarName-index variable to indicate the index of the input array that the Graphical Data Mapping editor is processing.

Note: The $VarName-index variable reports indexes after the Cardinality property is applied.

For example, you might have an input array with 6 elements. When you set the Cardinality property of a For each transform to 1,3, you are telling the Graphical Data Mapping editor that you only want to process index 1 and index 3 of your input array. In this use case, the $VarName-index has a value of 1 for the first entry and a value of 3 for the second entry.

You can use the variable $VarName-index as part of the XPath condition that you can define to filter inputs, or as part of any transformation within the nested map that is associated to the For each transform.

The fist value of $VarName-index is 1 when your input array is not empty.

The value of $VarName-index is 0 when your input array is empty. You must enable the Allow Empty input property.

Variable $VarName-count

In the nested mapping of the For Each transform, you can use the $VarName-count variable to determine the number of times the Graphical Data Mapping editor enters the nested mapping to allow populating the output array.

The variable $VarName-count initial value is 1 . The maximum value is determined by the Cardinality and the Filter Inputs properties that are applied.

You cannot use the variable $VarName-count as part of the XPath condition that you can define to filter inputs.

You can use the variable $VarName-count as part of any transformation within the nested map that is associated to the For each transform.

For example, you might have an input array with 6 elements.
  • When you set the Cardinality property of a For each transform to 1:3, you are telling the Graphical Data Mapping editor that you only want to process index 1, index 2 and index 3 of your input array. In this use case, the nested map is executed 3 times and the $VarName-count variable is equal to 1 the first time is executed, 2 the second time is executed, and then 3.
  • When you have a Filter expression that only matches index 1 and 3 of you input array, the $VarName-count variable is equal to 1 the first time the nested mapping is entered for the data of input index 1. The $VarName-count variable is equal to 2 on the second time the nested mapping is entered for the data of input index 3.

The value of $VarName-count is 1 when you enable Allow Empty input in a For each transform and the nested mapping is entered as a result of the empty condition.

Example 1: Filter inputs by configuring the cardinality property

In this example, the For Each transform only runs for a restricted number of elements of the repeating element. The rest of the elements in the array are not considered.

The For Each transform iterates over instances 2, 3, and 4 between the input element stock and the output element inventory.

This figure shows the For Each transform.

To restrict the number of instances, you can configure the Cardinality tab in the Properties page of the transform. You must set the following value in the Cardinality property tab:
2:4

This figure shows the Cardinality tab in the Properties page.

When you run the following message through the For Each transform,

<?xml version="1.0" encoding="UTF-8"?>
<tns:Input xmlns:tns="http://www.example.org/schema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.example.org/schema foo.xsd ">
  <tns:stock>
    <tns:name>apple</tns:name>
    <tns:number>1</tns:number>
    <tns:description>fruit</tns:description>
  </tns:stock>
  <tns:stock>
    <tns:name>banana</tns:name>
    <tns:number>2</tns:number>
    <tns:description>fruit</tns:description>
  </tns:stock>
  <tns:stock>
    <tns:name>cap</tns:name>
    <tns:number>3</tns:number>
    <tns:description>accessory</tns:description>
  </tns:stock>
  <tns:stock>
    <tns:name>door</tns:name>
    <tns:number>4</tns:number>
    <tns:description>furniture</tns:description>
  </tns:stock>
  <tns:stock>
    <tns:name>elephant</tns:name>
    <tns:number>5</tns:number>
    <tns:description>animal</tns:description>
  </tns:stock>
 </tns:Input>
you get the following output:

<?xml version="1.0" encoding="UTF-8"?><io:Output xmlns:io="http://www.example.org/schema">
  <io:inventory>
    <io:name>banana</io:name>
    <io:number>2</io:number>
    <io:description>fruit</io:description>
    <io:index>1</io:index>
    <io:count>1</io:count>
  </io:inventory>
  <io:inventory>
    <io:name>cap</io:name>
    <io:number>3</io:number>
    <io:description>accessory</io:description>
    <io:index>2</io:index>
    <io:count>2</io:count>
  </io:inventory>
  <io:inventory>
    <io:name>door</io:name>
    <io:number>4</io:number>
    <io:description>furniture</io:description>
    <io:index>3</io:index>
    <io:count>3</io:count>
  </io:inventory>
 </io:Output>

Example 2: Filter inputs by configuring the Filter Inputs property

In this example, the For Each transform only runs for a restricted number of elements of the repeating element. The rest of the elements in the array are not considered. The For Each transform iterates over instances where the name of a stock item is a string with more than 4 characters.

In the For Each transform, the input element is stock and the output element is inventory.

This figure shows the For Each transform.

The For Each transform iterates over instances where the value of stock.name is a string with more than 4 characters.

To restrict the number of instances, you can configure the Filter Inputs tab in the Properties page of the transform. You must set the following value in the Filter Inputs property tab:
fn:string-length($stock/io:name) > 4
This figure shows the Filter Inputs tab in the Properties page.

When you run the following message through the For Each transform,

<?xml version="1.0" encoding="UTF-8"?>
<tns:Input xmlns:tns="http://www.example.org/schema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.example.org/schema foo.xsd ">
  <tns:stock>
    <tns:name>apple</tns:name>
    <tns:number>1</tns:number>
    <tns:description>fruit</tns:description>
  </tns:stock>
  <tns:stock>
    <tns:name>banana</tns:name>
    <tns:number>2</tns:number>
    <tns:description>fruit</tns:description>
  </tns:stock>
  <tns:stock>
    <tns:name>cap</tns:name>
    <tns:number>3</tns:number>
    <tns:description>accessory</tns:description>
  </tns:stock>
  <tns:stock>
    <tns:name>door</tns:name>
    <tns:number>4</tns:number>
    <tns:description>furniture</tns:description>
  </tns:stock>
  <tns:stock>
    <tns:name>elephant</tns:name>
    <tns:number>5</tns:number>
    <tns:description>animal</tns:description>
  </tns:stock>
  <tns:stock>
    <tns:name>flower</tns:name>
    <tns:number>6</tns:number>
    <tns:description>decoration</tns:description>
  </tns:stock>
  <tns:stock>
    <tns:name>gold</tns:name>
    <tns:number>7</tns:number>
    <tns:description>money</tns:description>
  </tns:stock>
  <tns:stock>
    <tns:name>honey</tns:name>
    <tns:number>8</tns:number>
    <tns:description>food</tns:description>
  </tns:stock>
  <tns:stock>
    <tns:name>igloo</tns:name>
    <tns:number>9</tns:number>
    <tns:description>cold</tns:description>
  </tns:stock>
  <tns:stock>
    <tns:name>jeep</tns:name>
    <tns:number>10</tns:number>
    <tns:description>car</tns:description>
  </tns:stock>
</tns:Input>
you get the following output:

<?xml version="1.0" encoding="UTF-8"?><io:Output xmlns:io="http://www.example.org/schema">
  <io:inventory>
    <io:name>apple</io:name>
    <io:number>1</io:number>
    <io:description>fruit</io:description>
    <io:index>0</io:index>
    <io:count>1</io:count>
  </io:inventory>
  <io:inventory>
    <io:name>banana</io:name>
    <io:number>2</io:number>
    <io:description>fruit</io:description>
    <io:index>1</io:index>
    <io:count>1</io:count>
  </io:inventory>
  <io:inventory>
    <io:name>elephant</io:name>
    <io:number>5</io:number>
    <io:description>animal</io:description>
    <io:index>4</io:index>
    <io:count>2</io:count>
  </io:inventory>
  <io:inventory>
    <io:name>flower</io:name>
    <io:number>6</io:number>
    <io:description>decoration</io:description>
    <io:index>5</io:index>
    <io:count>3</io:count>
  </io:inventory>
  <io:inventory>
    <io:name>honey</io:name>
    <io:number>8</io:number>
    <io:description>food</io:description>
    <io:index>7</io:index>
    <io:count>4</io:count>
  </io:inventory>
  <io:inventory>
    <io:name>igloo</io:name>
    <io:number>9</io:number>
    <io:description>cold</io:description>
    <io:index>8</io:index>
    <io:count>5</io:count>
  </io:inventory>
</io:Output>

Example 3: Filter inputs by configuring the Cardinality and the Filter Inputs properties

In this example, the For Each transform only runs for the first three elements of the repeating element. The rest of the elements in the array are not considered. For each element in the array, if the first 4 characters of the element B start with UK01, then the transformation inside the nested map is executed.

Inside the nested map, the fn:concat transform calculates the value of element e based on the input element index and the input element D.

This figure shows the For Each transform.

When you run the following message through the For Each transform,

<?xml version="1.0" encoding="UTF-8"?>
<NewElement>
  <A>A1</A>
  <C>Field_1</C>
  <C>Field_2</C>  
  <C>Field_3</C>
  <D>1000</D>
  <E>CUSTOMER_AREA1</E>
</NewElement>
you get the following output:

<NewElement1>
	<c>
		<d/>
		<e>0_1000</e>
	</c>
</NewElement1>

Note: If the repeating element is empty, then the nested map is executed once because the option Allow Empty input is selected.
When you run the following message through the For Each transform,

<?xml version="1.0" encoding="UTF-8"?>
<NewElement>
  <A>A1</A>
  <B>UK011234567</B>
  <B>B2</B>
  <B>UK019999999</B>
  <B>UK01xxxxxxx</B>
  <C>Field_1</C>
  <C>Field_2</C>  
  <C>Field_3</C>
  <D>1000</D>
  <E>CUSTOMER_AREA1</E>
</NewElement>
you get the following output:

<NewElement1>
	<c>
		<d>UK011234567</d>
		<e>1_1000</e>
	</c>
	<c>
		<d>UK019999999</d>
		<e>3_1000</e>
	</c>
</NewElement1>