foreach
foreach element
Iterates through an ECMAScript array of items.
Syntax
<foreach
array = "ECMAScript_Expression"
item = "variable"
/>
Attributes
array |
Required. An ECMAScript expression that evaluates to an array. |
item |
Required. The variable that stores each array item upon each iteration of the loop. |
Parents
block, catch, error, filled, foreach, help, if, noinput, nomatch, prompt
Children
assign, audio, break, clear, data, disconnect, emphasis, enumerate, exit, foreach, goto, if, log element, mark, p element, phoneme, prompt, prompt, reprompt, return, s element, say-as, script, sub, submit, throw, value, var, voice
Remarks
The most common use of foreach is to play back an array of audio prompts.
If the array attribute does not evaluate to an array, the interpreter throws a generic error event prior to Revision 3, or error.semantic in Revision 3 and later.
Prior to Revision 3, evaluation of the array expression occurs each time through the loop. In Revision 3 and later, the evaluation occurs just once.
Examples
The following example iterates through an array of fruits and plays them back to the user.
<?xml version="1.0"?>
<vxml version="2.1"
xmlns="http://www.w3.org/2001/vxml">
<form id="play_fruit">
<block>
<!-- create an array of fruit names -->
<var name="aFruit" expr="new Array('apples', 'oranges', 'pears', 'bananas')"/>
Here's a list of fruit we have available today
<!-- iterate throught through each item in the array -->
<foreach item="fruit" array="aFruit">
<value expr="fruit"/>
</foreach>
</block>
</form>
</vxml>
The VoiceXML example that follows is driven by the following XML data:
<?xml version="1.0"?>
<?access-control allow="*"?>
<subjects>
<subject id="s1">
<name>Overview</name>
</subject>
<subject id="s2">
<name>Design</name>
</subject>
<subject id="s3">
<name>Audio</name>
</subject>
<subject id="s4">
<name>Development</name>
</subject>
<subject id="s5">
<name>Tuning</name>
</subject>
</subjects>
The VoiceXML example that follows references the following SRGS grammar:
<?xml version= "1.0"?>
<grammar mode="voice"
root="root_rule"
tag-format="semantics/1.0"
version="1.0"
xml:lang="en-US"
xmlns="http://www.w3.org/2001/06/grammar">
<rule id="root_rule" scope="public">
<one-of>
<item>
<one-of>
<item>
overview
</item>
<item>
general
</item>
</one-of>
<tag>out.subject = "1";</tag>
</item>
<item>
design
<tag>out.subject = "2";</tag>
</item>
<item>
<one-of>
<item>
production
</item>
<item>
audio
</item>
</one-of>
<tag>out.subject = "3";</tag>
</item>
<item>
<one-of>
<item>
development
</item>
<item>
voice x m l
</item>
</one-of>
<tag>out.subject = "4";</tag>
</item>
<item>
tuning
<tag>out.subject = "5";</tag>
</item>
</one-of>
</rule>
</grammar>
The following example plays back a list of subjects retrieved using the data element. If the data cannot be retrieved, or the data doesn't contain any subjects, an appropriate message is played to the user, and the application is terminated. If the subjects are retrieved successfully, the id and name of each subject is transferred to an ECMAScript array, and the foreach element iterates through the array, playing back a subject name upon each iteration using the audio element.
<?xml version="1.0"?>
<vxml version="2.1"
xmlns="http://www.w3.org/2001/vxml">
<catch event="error.badfetch">
<log>badfetch: unable to fetch subject data or subject grammar</log>
<!-- <exit/> -->
</catch>
<var name="fRepeating" expr="false"/>
<script><![CDATA[
// Build an array of subjects based on the data returned by the data element
function GetSubjects(oData)
{
var aSubjects = [];
try {
var oRoot = oData.documentElement;
var oSubjects = oRoot.getElementsByTagName("subject");
for (var i = 0; i < oSubjects.length; i++)
{
var oSubject = oSubjects.item(i);
var sID = oSubject.getAttribute("id");
var sName = oSubject.getElementsByTagName("name").item(0).firstChild.data;
aSubjects.push({"wav" : sID + ".wav", "tts" : sName});
}
}
catch(e)
{
vxmllog("GetSubjects: error extracting data from XML document");
}
return aSubjects;
}
// return data about the subject specified by its id
function GetSubjectById(oData, sDesiredID)
{
var oRoot = oData.documentElement;
// BUGBUG: use Node.getElementById when Platform supports it
var oSubjects = oRoot.getElementsByTagName("subject");
for (var i = 0; i < oSubjects.length; i++)
{
var oSubject = oSubjects.item(i);
var sCurrentID = oSubject.getAttribute("id");
if (sDesiredID == sCurrentID)
{
var sName = oSubject.getElementsByTagName("name").item(0).firstChild.data;
return {"name" : sName};
}
}
return null;
}
]]></script>
<form id="list_subjects">
<!-- provider of subject data -->
<data src="subjects.exml" name="oSubjects"/>
<!-- holds array of subjects -->
<var name="aSubjects"/>
<block cond="typeof(oSubjects) != 'object' || null == oSubjects">
Information on subjects is unavailable.
<exit />
</block>
<block cond="oSubjects">
<assign name="aSubjects" expr="GetSubjects(oSubjects)"/>
</block>
<block cond="!aSubjects || !aSubjects.length">
There are no subjects available.
<exit />
</block>
<block cond="!fRepeating">
Here's a list of subjects.
When you hear the one you want, just say it.
</block>
<field name="subject">
<prompt>
<foreach item="oSubject" array="aSubjects">
<audio expr="oSubject.wav">
<value expr="oSubject.tts"/>
</audio>
</foreach>
</prompt>
<grammar src="subjects-voice.grxml" mode="voice" type="application/srgs+xml"/>
<nomatch>
I'm sorry. I didn't get that.
Please pick a subject you're interested in.
<reprompt/>
</nomatch>
<noinput>
<!-- end of the list -->
<goto next="#query_repeat_list"/>
</noinput>
<filled>
<log>Recognized <value expr="subject"/></log>
<var name="oSubject" expr="GetSubjectById(oSubjects, 's' + subject)"/>
<if cond="oSubject">
You chose <value expr="oSubject.name"/>
<else/>
<log>subject id <value expr="subject"/>
returned by grammar unavailable in data.</log>
I'm sorry. That subject you requested is unavailable.
Here's the list of subjects.
<clear namelist="subject"/>
<assign name="fRepeating" expr="true"/>
<reprompt/>
</if>
<exit />
</filled>
</field>
</form>
<form id="query_repeat_list">
<field type="boolean" name="again">
<prompt>That's the list of subjects. Do you wanna hear them again?</prompt>
<catch event="noinput nomatch">
Sorry. I didn't get that.
<reprompt/>
</catch>
<filled>
<if cond="again">
<assign name="fRepeating" expr="true"/>
<goto next="#list_subjects"/>
<else/>
<exit />
</if>
</filled>
</field>
</form>
</vxml>