Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Tag

Optional/Required

Description
ForRequiredLoop 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]

  • One variable form: each=”var_name” this is used to iterate over values

  • Two variables form: each=”key_var:value_var” this is used to iterate over entries (i.e. key:value pairs)
  • Two variables form can be used to define only one (e.g. “key_var:” or “:value_var”)

  • Variable names can be “deep” i.e. contain dots in them (e.g. “obj.type:obj.value”)

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

FAQ

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

Code Block
languagexml
themeEclipse
titleIterating over Query Result
<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>
#QuestionAnswerReason
1

How do I determine the number of iterations of a for loop?

Code Block
languagexml
themeEclipse
titleIterating over Query Result
<Query>
  <Find format="all">
    <VendorInfo>
      <vendorId ne=""/>
    </VendorInfo>
  </Find>
  <For Each="v" IN="$Response.Message.Value.Find.Result.VendorInfo.vendorId">
    <Log Message="In Loop...: [:$LocalData.k:]"/>
    <Log Message="[:$LocalData.v:]"/>
  </For>
</Query>
Size of the loop is 1.

Number of iterations is always determined by the Number of Containers from the specified source.

Example: Here Source is: $Response.Message.Value.Find

There is only one container with <Find>






Tips and Caveats

  • If you use $LocalData your loop variables will NOT be available after the loop (they are defined in the scope of iteration only)
  • 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

    Code Block
    languagexml
    themeEclipse
    titleAssign STRUCTURE
    <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 

    Code Block
    languagexml
    themeEclipse
    titleAssign to STRUCTURE
    <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>

...