Business Process and Data Transformation Language Reference
DTL <foreach>
[Back] [Next]
   
Server:docs2
Instance:LATEST
User:UnknownUser
 
-
Go to:
Search:    

Define a sequence of activities to be executed iteratively.
Synopsis
<foreach property="P1" key="K1">
  ...
</foreach> 
Attributes
Attribute Description Value
property Required. The collection property (list or array) to iterate over. It must be the name of a valid object and property in the execution context. A string of one or more characters.
key Required. The index used to iterate through the collection. It must be a name of a valid object and property in the execution context. It is assigned a value for each element in the collection. A string of one or more characters.
Elements
Element Purpose
<annotation> Optional. A text string that describes the <foreach> element.
Most activities Optional. <foreach> may contain zero or more of the following elements in any combination: <assign>, <code>, <foreach>, <if>, <sql>, <subtransform>, or <trace>.
Description
The <foreach> element defines a sequence of activities that are executed iteratively, once for every element that exists within a specified collection property. If the element is null, the sequence is not executed. The sequence is executed if the element has an empty value, that is, the separators are there but there is no value between them, but is not executed for a null value, that is, the message is terminated before the field is specified.
For example:
<foreach key='i' property='target.{PID:3()}'>
   <assign property='target.{PID:3(i).4}' value='"001"' action='set'/>
 </foreach>
Or:
<foreach key='key' property='source.{PID:PatientIDInternalID()}'>
 <if condition='source.{PID:PatientIDInternalID(key).identifiertypecode}="PAS"'>
  <true>
   <assign property='target.{PID:PatientIdentifierList(key).identifiertypecode}'
           value='"MR"'
           action='set'/>
  </true>
 </if>
 <if condition='source.{PID:PatientIDInternalID(key).identifiertypecode}="GMS"'>
  <true>
   <assign property='target.{PID:PatientIdentifierList(key).identifiertypecode}'
           value='"MC"'
           action='set'/>
   <assign property='target.{PID:PatientIdentifierList(key).assigningfacility}'
           value='"AUSHIC"'
           action='set'/>
  </true>
 </if>
</foreach>
The properties referenced by the <foreach> element must be properties in the source or target object for the data transformation.
Nested <foreach>
Nesting of <foreach> elements is allowed; for example:
<transform targetClass='EnsLib.HL7.Message'
           targetDocType='2.3.1:BAR_P01'
           sourceClass='EnsLib.HL7.Message'
           sourceDocType='2.3.1:BAR_P01'
           create='new'
           language='objectscript'>
  <assign property='target.{MSH}' value='source.{MSH}' action='set'/>
  <assign property='target.{MSH:4}' value='"A"' action='set'/>
  <assign property='target.{MSH:6}' value='"A"' action='set'/>
  <assign property='target.{MSH:13}' value='source.{MSH:10}' action='set'/>
  <assign property='target.{MSH:10}' value='source.{MSH:13}' action='set'/>
  <assign property='target.{EVN}' value='source.{EVN}' action='set'/>
  <assign property='target.{PID}' value='source.{PID}' action='set'/>
  <assign property='target.{PID:2.4}' value='"A"' action='set'/>
  <foreach key='i' property='source.{PID:3()}'>
    <assign property='target.{PID:3(i).4}'
            value='"A"'
            action='set'/>
  </foreach>
  <assign property='target.{PID:18.4}' value='"A"' action='set'/>
  <foreach key='i' property='source.{PV1grp()}'>
    <assign property='target.{PV1grp(i).PV1}'
            value='source.{PV1grp(i).PV1}'
            action='set'/>
    <foreach key='j' property='source.{PV1grp(i).DG1()}'>
      <assign property='target.{PV1grp(i).DG1(j)}'
              value='source.{PV1grp(i).DG1(j)}'
              action='set'/>
    </foreach>
    <foreach key='k' property='source.{PV1grp(i).PR1grp()}'>
      <assign property='target.{PV1grp(i).PR1grp(k).PR1}'
              value='source.{PV1grp(i).PR1grp(k).PR1}'
              action='set'/>
    </foreach>
  </foreach>
</transform>
While this <foreach> syntax is a valid example, it can be streamlined, as explained in the next topic.
Shortcuts for <foreach>
When you are working with a document-based message or “virtual document” type such as an HL7 message, the <assign> statement offers a shortcut notation that iterates through every instance of a repeating field within a document structure. This means you do not actually need to set up <foreach> loops with 'i' 'j' and 'k' just for the purpose of handling repeating fields. Instead, you can use a much simpler notation with empty parentheses, as shown below:
<assign property='target.{PID:3().4}' value='"001"' action='set'/>
This single line of DTL syntax has the same meaning as the three lines shown below:
<foreach key='i' property='target.{PID:3()}'>
   <assign property='target.{PID:3(i).4}' value='"001"' action='set'/>
 </foreach>
The parentheses shortcut works for a nested <foreach> as well. The following <transform> example is functionally identical to the <transform> containing a nested <foreach> shown on the previous page. This version uses the parentheses shortcut for repeating fields, and omits an action value since 'set' is the default action for <assign>:
<transform targetClass='EnsLib.HL7.Message'
           targetDocType='2.3.1:BAR_P01'
           sourceClass='EnsLib.HL7.Message'
           sourceDocType='2.3.1:BAR_P01'
           create='new'
           language='objectscript'>
<assign property='target.{MSH}' value='source.{MSH}'/>
<assign property='target.{MSH:4}' value='"A"'/>
<assign property='target.{MSH:6}' value='"A"'/>
<assign property='target.{MSH:13}' value='source.{MSH:10}'/>
<assign property='target.{MSH:10}' value='source.{MSH:13}'/>
<assign property='target.{EVN}' value='source.{EVN}'/>
<assign property='target.{PID}' value='source.{PID}'/>
<assign property='target.{PID:2.4}' value='"A"'/>
<assign property='target.{PID:3().4}' value='"A"'/>
<assign property='target.{PID:18.4}' value='"A"'/>
<assign property='target.{PV1grp().PV1}' value='source.{PV1grp().PV1}'/>
<assign property='target.{PV1grp().DG1()}' value='source.{PV1grp().DG1()}'/>
<assign property='target.{PV1grp().PR1grp().PR1}'
        value='source.{PV1grp().PR1grp().PR1}'/>
</transform>
Avoiding <STORE> Errors with Large Messages
As you loop over segments in an HL7 message or object collections, they are brought into memory. If these objects consume all the memory assigned to the current process, you may get unexpected errors.
To avoid this, remove the objects from memory after you no longer need them. For example, if you are processing many HL7 segments in a <foreach> loop, you can call the commitSegmentByPath method on both the source and target as the last step in the loop. Similarly, for object collections, use the %UnSwizzleAt method.
For example:
<foreach property='source.{ORCgrp()}' key='tORCkey'>
<foreach property='source.{ORCgrp(tORCkey).OBRgrp()}' key='tOBRkey'>
<foreach property='source.{ORCgrp(tORCkey).OBRgrp(tOBRkey).OBXgrp()}' key='tOBXkey'>

<assign property='target.{ORCgrp(tORCkey).OBRgrp(tOBRkey).OBR:4.1}' value='"XYZ"' action='set'/>

<code>
<![CDATA[
 Do source.commitSegmentByPath
("ORCgrp("_tORCkey_").OBRgrp("_tOBRkey_").OBXgrp("_tOBXkey_").OBX")
 Do target.commitSegmentByPath("ORCgrp("_tORCkey_").OBRgrp("_tOBRkey_").OBXgrp("_tOBXkey_").OBX")
  ]]>

</code>

</foreach>
</foreach>
</foreach>
If you cannot make code changes, a temporary workaround is to increase the amount of memory allocated for each process. You can change this by setting the bbsiz parameter on the Advanced Memory Settings page in the Management Portal. Note that this requires a system restart and should only occur after consulting with your system administrator.