The for each statement enumerates the elements of a collection, executing an embedded statement for each element of the collection.
<For each=”<variable[s]>” in=”<source data key>” from=”<source data key prefix>” using="<variable store key>"> …facet script … </For> |
Examples of each of these variations will be provided in the next section.
Tag | Optional/Required | Description |
---|---|---|
For | Required | Loop is implemented as a generic FacetScript construct and NOT specific to any facet so you can use it anywhere FacetScript can be used. |
Each= | Required | "each" defines loop variable[s] name[s]
|
in= | Required | “in” specifies the source key to iterate over |
from= | Optional | “from” specifies the source key prefix. Default value is “$Response.Message.Value”. That is, loop will [virtually] concatenate from+in to obtain actual key and some optimizations. |
using= | Optional | “using” specifies the data store where loop variable[s] will be allocated. Default value is “$LocalData”. That is, since loop body is a scope, a new loop variable[s] will be created for each loop iteration. If you need to pass/keep some data between iteration then you can use a different store (e.g. $ProcessData, $ContextData etc.), combination of stores or wrap loop in another scope and initialize your data there |
In this section let's try to understand For Each in a FAQ style of documentation. For all questions below: Let's take VendorInfo to contain three Vendors
<Find Status="Success" Format="all"> <Result> <VendorInfo QName="Atomiton.Sensors.VendorInfo"> <vendorId>vendorA</vendorId> <vendorCity Value="Calgary" Known="Calgary" Version="1" Timestamp="1489093271736" DateTime="2017-03-09 13:01:11.736" QName="Atomiton.Sensors.VendorInfo.vendorCity" FName="vendorCity"/> <vendorName Value="Phidget" Known="Phidget" Version="1" Timestamp="1489093271734" DateTime="2017-03-09 13:01:11.734" QName="Atomiton.Sensors.VendorInfo.vendorName" FName="vendorName"/> </VendorInfo> </Result> <Result> <VendorInfo QName="Atomiton.Sensors.VendorInfo"> <vendorId>vendorB</vendorId> <vendorCity Value="Calgary" Known="Calgary" Version="1" Timestamp="1489093277295" DateTime="2017-03-09 13:01:17.295" QName="Atomiton.Sensors.VendorInfo.vendorCity" FName="vendorCity"/> <vendorName Value="Phidget" Known="Phidget" Version="1" Timestamp="1489093277294" DateTime="2017-03-09 13:01:17.294" QName="Atomiton.Sensors.VendorInfo.vendorName" FName="vendorName"/> </VendorInfo> </Result> <Result> <VendorInfo QName="Atomiton.Sensors.VendorInfo"> <vendorId>vendorC</vendorId> <vendorCity Value="Calgary" Known="Calgary" Version="1" Timestamp="1489093282311" DateTime="2017-03-09 13:01:22.311" QName="Atomiton.Sensors.VendorInfo.vendorCity" FName="vendorCity"/> <vendorName Value="Phidget" Known="Phidget" Version="1" Timestamp="1489093282311" DateTime="2017-03-09 13:01:22.311" QName="Atomiton.Sensors.VendorInfo.vendorName" FName="vendorName"/> </VendorInfo> </Result> </Find> |
# | Question | Explaination | |
---|---|---|---|
1 | How do I determine the number of iterations of a for loop?
| Number of iterations is always determined by the Number of Containers from the specified source and Each is a single variable format. Example: Here Source is: $Response.Message.Value.Find
| |
2 | What happens if I do not specify value in Each i.e Each="k:v"
|
| |
3 | What happens if we provide only one variable in key/value format i.e either k: or :v
|
|
We are manipulating structures, so the general idea is to assign a STRUCTURE to a loop variable so you can manipulate the CONTENT of the structure through the variable. That is, <For each=”val” in=”Find.Result.VendorInfo.VendorTitle.Value”> will allow you to do if/select on the val, but will NOT allow you to change the VendorTitle, only the value of loop variable which is a simple value in this case.
Caveat Example
<Query> <Find format="Version"> <VendorInfo> <vendorTitle eq="Sensor Provider"/> </VendorInfo> </Find> <For each="val" in="Find.Result.VendorInfo.VendorTitle.Value"> <IF Condition="/'[:$LocalData.val:]' eq 'Sensor Provider'"> <!-- This is simply to show how if can be used --> <Log Message="Found Sensor Provider"/> </IF> <SetLocalData Key="val" Value="Actuator Provider"/> <!-- This will change <Value> only --> </For> <!-- Do an Update --> <Update> <From>Result</From> <Include>$Response.Message.Value.Find</Include> </Update> </Query> <!-- Result is.. --> <Find Status="Success" Format="version"> <Result> <VendorInfo> <VendorSysId>KQN7B5X7AAAAUAABBN7HUYCE</VendorSysId> <vendorTitle Value="Sensor Provider" Version="1"/> <vendorName Value="Libelium" Version="2"/> </VendorInfo> </Result> <Result> <VendorInfo> <VendorSysId>KQN7BUUZAAAAUAABBPXOPXWG</VendorSysId> <vendorTitle Value="Sensor Provider" Version="1"/> <vendorName Value="Phidget" Version="1"/> </VendorInfo> </Result> <Result> <VendorInfo> <VendorSysId>KQN7CBXVAAAAUAABBNFHWPBK</VendorSysId> <vendorTitle Value="Sensor Provider" Version="1"/> <vendorName Value="Phidget3" Version="1"/> </VendorInfo> </Result> </Find> <Update Status="Success" Format="version"> <VendorInfo> <VendorSysId>KQN7B5X7AAAAUAABBN7HUYCE</VendorSysId> <vendorName Status="Success_NoAction:2:1460829683086;" Value="Libelium" Version="2"/> <vendorTitle Status="Success_NoAction:1:1460757657344;" Value="Sensor Provider" Version="1"/> <!-- Note there is no change in value --> </VendorInfo> <VendorInfo> <VendorSysId>KQN7BUUZAAAAUAABBPXOPXWG</VendorSysId> <vendorName Status="Success_NoAction:1:1460757648025;" Value="Phidget" Version="1"/> <vendorTitle Status="Success_NoAction:1:1460757648027;" Value="Sensor Provider" Version="1"/> <!-- Note there is no change in value --> </VendorInfo> <VendorInfo> <VendorSysId>KQN7CBXVAAAAUAABBNFHWPBK</VendorSysId> <vendorName Status="Success_NoAction:1:1460757661429;" Value="Phidget3" Version="1"/> <vendorTitle Status="Success_NoAction:1:1460757661429;" Value="Sensor Provider" Version="1"/> <!-- Note there is no change in value --> </VendorInfo> </Update> |
Correct way is to point val → Find.Result.VendorInfo
<Query> <Find format="Version"> <VendorInfo> <vendorTitle eq="Sensor Provider"/> </VendorInfo> </Find> <For each="val" in="Find.Result.VendorInfo"> <IF Condition="/'[:$LocalData.val.vendorTitle.Value:]' eq 'Sensor Provider'"> <Log Message="Found Sensor Provider"/> </IF> <SetLocalData Key="val.vendorTitle.Value" Value="Actuator Provider"/> </For> <!-- Do an Update --> <Update> <From> Result </From> <Include> $Response.Message.Value.Find </Include> </Update> </Query> <!-- Result is --> <Find Status="Success" Format="version"> <Result> <VendorInfo> <VendorSysId>KQN7B5X7AAAAUAABBN7HUYCE</VendorSysId> <vendorTitle Version="3" Value="Actuator Provider"/> <vendorName Value="Libelium" Version="2"/> </VendorInfo> </Result> <Result> <VendorInfo> <VendorSysId>KQN7BUUZAAAAUAABBPXOPXWG</VendorSysId> <vendorTitle Version="3" Value="Actuator Provider"/> <vendorName Value="Phidget" Version="1"/> </VendorInfo> </Result> <Result> <VendorInfo> <VendorSysId>KQN7CBXVAAAAUAABBNFHWPBK</VendorSysId> <vendorTitle Version="3" Value="Actuator Provider"/> <vendorName Value="Phidget3" Version="1"/> </VendorInfo> </Result> </Find> <Update Status="Success" Format="version"> <VendorInfo> <VendorSysId>KQN7B5X7AAAAUAABBN7HUYCE</VendorSysId> <vendorName Status="Success_NoAction:2:1460829683086;" Value="Libelium" Version="2"/> <vendorTitle Status="Success=Updated:4:1460935288963;" Value="Actuator Provider" Version="4"/> <!-- Title is updated --> </VendorInfo> <VendorInfo> <VendorSysId>KQN7BUUZAAAAUAABBPXOPXWG</VendorSysId> <vendorName Status="Success_NoAction:1:1460757648025;" Value="Phidget" Version="1"/> <vendorTitle Status="Success=Updated:4:1460935288964;" Value="Actuator Provider" Version="4"/> <!-- Title is updated --> </VendorInfo> <VendorInfo> <VendorSysId>KQN7CBXVAAAAUAABBNFHWPBK</VendorSysId> <vendorName Status="Success_NoAction:1:1460757661429;" Value="Phidget3" Version="1"/> <vendorTitle Status="Success=Updated:4:1460935288964;" Value="Actuator Provider" Version="4"/> <!-- Title is updated --> </VendorInfo> </Update> |
<Query> <Find format="Version"> <VendorInfo> <vendorSysId ne=""/> </VendorInfo> </Find> <For each="val" in="Find.Result.VendorInfo"> <!-- Note that since From is not specified: It will default to $Response.Message.Value --> <Log Message="Vendor Name is: [:$LocalData.val.vendorName.Value:]"/> </For> </Query> |
<SetContextData Key="Atomiton.FS.Features.1" Value="Conditional Statements"/> <SetContextData Key="Atomiton.FS.Features.2" Value="For Statements"/> <SetContextData Key="Atomiton.FS.Features.3" Value="Case Statements"/> <!-- Let's iterate over ContextData --> <For each="val" In="Atomiton.FS.Features" From="$ContextData"> <Log Message="...[:$LocalData.val:]"/> </For> |
<SetContextData Key="Atomiton.FS.Features.1" Value="Conditional Statements"/> <SetContextData Key="Atomiton.FS.Features.2" Value="For Statements"/> <SetContextData Key="Atomiton.FS.Features.3" Value="Case Statements"/> <!-- Let's iterate over ContextData and use ProcessData to store iterated data --> <For each="val" in="Atomiton.FS.Features" from="$ContextData" using="$ProcessData"> <Log Message="within loop...[:$ProcessData.val:]"/> </For> |
<For each="light" in="Message.Value.lights" from="$ContextData.response"> <SetContextData key="state"> <value> <intensityLevel>-1</intensityLevel> <powerConsumption>-1</powerConsumption> <reliability>0</reliability> </value> </SetContextData> <if condition="[:$LocalData.light.location/count(latitude) gt 0:]"> <then> ... </then> </if> </For> |
<For each="key:val" in="[:SUBSCRIPTIONS:]" from="$FacetData"> <if condition="/'[:$LocalData.key:]' = '[:$Macro.Argument.Name:]'"> <Log Message="[:$LocalData.val:]"/> </if> </For> |