Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 2 Next »

 

Description

The for each statement enumerates the elements of a collection, executing an embedded statement for each element of the collection.

Syntax

For Statement Syntax
<For each=”<variable[s]>” in=”<source data key>” from=”<source data key prefix>” using="<variable store key>">
                …facet script …
</For>

Syntax Notes

Examples of each of these variations will be provided in the next section.

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

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

    Assign 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 

    Assign 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>

Examples

If then else with constant expression
<if condition="true"> 
<then>
  <Log Message="I am in true block!"/>
</then>
<else>
  <Log Message='I am in false block!"/>
</else>
If then else with constant expression
<if condition="true"> 
<then>
  <Log Message="I am in true block!"/>
</then>
<else>
  <Log Message='I am in false block!"/>
</else>
Boolean value stored in some user defined tags
<if condition="[:RuntimeParams.EnforceKey:]"> 
<then>
  <Log Message="I am in true block!"/>
</then>
<else>
  <Log Message="I am in false block!"/>
</else>
  </if>
</Query>

Special Tags when used with TQL

There are two ways in which XPath Expressions can be used as part of boolean expression.

a) XPath as part of individual operand of the expression. For example: $ContextData/projectkey below.

Boolean Expression for string comparison.
<if condition="$ContextData/projectKey eq '[:RuntimeParams.ProjectSettings_ProjectKey:]'">
  <then>
  <Log Message="I am in true block!"/>
</then>
<else>
  <Log Message="I am in false block!"/>
</else>
</if>

b) Whole boolean expression itself can be XPath expression. This is done using by starting the expression with "/"

Entire Boolean Expression as XPath
<if condition="/'[:$Macro.Argument.StopWid:]' != '' and '[:$Macro.Argument.StopTarget:]' != ''">
  <then>
  <Log Message="I am in true block!"/>
</then>
<else>
  <Log Message="I am in false block!"/>
</else>
</if>

Using Multiple operands

Take a special note in second expression the >= within boolean expression must be escaped. For example: >= is written as &gt;=

Multiple Operands
<if condition="[:$Macro.Argument.RouteLoc:]/not(boolean(Site)) and '[:$Macro.Argument.SelfWid:]' != '' and '[:$Macro.Argument.StopTarget:]' != ''">
    <then>
  <Log Message="I am in true block!"/>
</then>
<else>
  <Log Message="I am in false block!"/>
</else>
</if>
 
<if condition="/'[:$Macro.Argument.SiteCur:]' = '[:CONFIG.CompanyId:]' or
                       [:$ProcessData.$BTV.Worker.SlackCounter:] &gt;= [:CONFIG.RULES.MaxWorkerSlack:] or
                       [:$LocalData.Rand:] &gt; [:$ProcessData.$BTV.Worker.SlackTendency:]">
 <then>
   <Log Message="I am in true block!"/>
 </then>
 <else>
   <Log Message="I am in false block!"/>
 </else>
</if>

Nested If Statements

Note that if you do not have else, usage of <then> is optional.

Multiple Operands
<if condition="/'[:$Macro.Argument.StopWid:]' != '' and '[:$Macro.Argument.StopTarget:]' != ''">
        <Log Message="I am in true block!"/>
        <if condition="/'[:$Macro.Argument.SiteCur:]' = '[:CONFIG.CompanyId:]' or
                       [:$ProcessData.$BTV.Worker.SlackCounter:] &gt;= [:CONFIG.RULES.MaxWorkerSlack:] or
                       [:$LocalData.Rand:] &gt; [:$ProcessData.$BTV.Worker.SlackTendency:]">
        <Log Message="I am in true, true block!"/>
        </if>
</if>
  • No labels