第三节 Executable Content
|
|
|
可执行内容指的是一段程序逻辑。例如出现在 |
|
·form item <block>元素中; |
|
·<form>元素或input item的<filled>元素中; |
|
·事件处理中(<catch>,<help>元素等)。 |
|
可执行元素按照它们的文档顺序被依次执行。如果某个可执行元素产生一个错误,则这个错误马上被抛出。其后的可执行元素就不会被执行了。 |
|
这一节描述的是出现在可执行内容中的元素。 |
|
一、VAR |
|
<var>元素用于声明一个变量。它可以出现在任何可执行的内容中,也可以作为<form>元素或<vxml>元素的子元素出现。例如: |
|
<var name="phone" expr="'6305551212'"/>
<var name="y" expr="document.z+1"/>
|
|
如果它出现在可执行的内容中,它声明的变量作用域为anonynous,且作用在包含它的<block>,<filled>或<catch>元素中。在这种情况下,只有<var>元素被执行的时候才声明该变量。如果该变量在这个作用域已经声明了,则其后的声明将被看作是赋值,就像在ECMAScript中一样。 |
|
如果<var>元素作为<form>元素的子元素出现,则它声明的变量的作用域为该form的dialog。在这种情况下,在该form的初始化阶段就进行变量声明(详见2.1.6.1节)。<var>元素不是一个form item,因此,它不能被FIA的主循环访问。 |
|
如果<var>元素作为<vxml>元素的子元素出现,它声明的变量的作用域为document;如果该文档是应用根文档,它声明的变量的作用域为application。当文档被初始化的时候就进行变量声明,且初始化是按照文档的顺序进行的。 |
|
它的属性有: |
name |
保存变量值的变量名。 |
expr |
该变量的初始值(可选的)。如果没有指定该属性,该变量保持它当前的值(如果它当前有值的话);如果没有给定初始值,变量初始值默认为ECMAScript的undefined。 |
|
表44:<var>元素的属性 |
|
二、ASSIGN |
|
<assign>元素用来给变量赋值: |
|
<assign name="flavor" expr="'chocolate'"/>
<assign name="document.mycost" expr="document.mycost+14"/>
|
|
给没有用<var>元素或在<script>元素中的var语句显式声明的变量赋值是非法的。试图给一个没有声明的变量赋值,平台会抛出error.semantic事件。 |
|
注意:如果一个ECMAScript对象已经被正确地初始化(例如“obj”),则它的属性(例如“obj.prop1”)没有显式声明就可以给它赋值(实际上,如果试图声明ECMAScript对象的属性,如声明“obj.prop1”平台会抛出error.semantic事件)。 |
|
<assign>元素的属性: |
name |
要被赋值的变量名。 |
expr |
要赋给该变量的值。 |
|
表45:<assign>元素的属性 |
|
三、CLEAR |
|
<clear>元素的作用是重置(清零)一个或多个变量,包括form item。重置form item包括以下的操作: |
|
1、把该form item变量置为ECMAScript的undefined。 |
|
2、重新初始化该form item的提示语计数器和事件计数器。 |
|
例如: |
|
<clear namelist="city state zip"/>
|
它的属性有: |
namelist |
要重置的变量清单,它除了可以包括form item也可以包括变量名。如果没有指定,当前form的所有form item都被重置。 |
|
表46:<clear>元素的属性 |
|
四、IF, ELSEIF, and ELSE |
|
<if>元素用于判断条件逻辑,它可以和<elseif>、<else>搭配使用。 |
|
<if cond="total > 1000">
<prompt>This is way too much to spend.</prompt>
</if>
<if cond="amount < 29.95">
<assign name="x" expr="amount"/>
<else/>
<assign name="x" expr="29.95"/>
</if>
<if cond="flavor == 'vanilla'">
<assign name="flavor_code" expr="'v'"/>
<elseif cond="flavor == 'chocolate'"/>
<assign name="flavor_code" expr="'h'"/>
<elseif cond="flavor == 'strawberry'"/>
<assign name="flavor_code" expr="'b'"/>
<else/>
<assign name="flavor_code" expr="'?'"/>
</if>
|
|
|
五、PROMPT |
|
提示语可以<prompt>元素的一般形式出现在可执行内容中,除非不使用<prompt>元素的count属性。特别的,它的cond属性也可用在可执行内容中。提示语可以被封装在<prompt>和</prompt>中,或使用PCDATA表示。只要是<prompt>元素允许出现的地方,使用PCDATA xyz等价于使用<prompt>xyz</prompt>。 |
|
<nomatch count="1">
To open the pod bay door, say your code phrase clearly.
</nomatch>
<nomatch count="2">
<prompt>
This is your <emphasis>last</emphasis> chance.
</prompt>
</nomatch>
<nomatch count="3">
Entrance denied.
<exit/>
</nomatch>
|
|
六、REPROMPT |
|
在处理一个事件的过程中,FIA需要一个<catch>元素对适当的提示语进行排队。因此,在执行完一个<catch>元素后的下一次循环中,FIA一般不会进行正常的选定和提示语排队。然而,有两种情况下,FIA在执行完一个<catch>元素后的下一次循环中,会进行正常的选定和提示语排队: |
|
1、如果在<catch>元素中执行了<goto>元素或<submit>元素,跳转到另一个dialog,或者执行了一个<return>元素,从一个subdialog中返回,在这些情况下,新的dialog需要保证它的初始提示语保持原样; |
|
2、如果在<catch>元素中执行了一个<reprompt>元素,要求FIA随后要重新播放提示语。 |
|
在这两种情况中,FIA选定下一个要访问的form item之后,会执行正常的提示语处理,包括选定该form item的提示语,对提示语进行排队,和给该form item的提示语计数器加1。 |
|
例如,下面的例子中的noinput事件处理希望FIA访问下一个form item时,选定并播放它的提示语: |
|
<field name="want_ice_cream">
<grammar type="application/srgs+xml" src="/grammars/boolean.grxml"/>
<prompt>Do you want ice cream for dessert?</prompt>
<prompt count="2">
If you want ice cream, say yes.
If you do not want ice cream, say no.
</prompt>
<noinput>
I could not hear you.
<!-- Cause the next prompt to be selected and played. -->
<reprompt/>
</noinput>
</field>
|
|
可能的一个对话流程: |
|
C: Do you want ice cream for dessert?
H: (silence)
C: I could not hear you.
C: If you want ice cream, say yes. If you don't want ice cream, say no.
H: (silence)
C: I could not hear you.
C: If you want ice cream, say yes. If you don't want ice cream, say no.
H: No.
|
|
如果该例子中没有<reprompt>元素,上面的流程变为如下所示: |
|
C: Do you want ice cream for dessert?
H: (silence)
C: I could not hear you.
H: (silence)
C: I could not hear you.
H: No.
|
|
注意,上面的例子中之所以略过了提示语选择阶段,是因为在执行完一个<catch>元素后(没有执行<reprompt>元素,或没有通过<goto>、<submit>、<return>元素跳转到另一个dialog),被FIA选定的该form item的提示语计数器并没有加1。 |
|
同时注意,执行一个<catch>元素后(没有执行<reprompt>元素,或没有通过<goto>、<submit>、<return>元素跳转到另一个dialog),FIA选定的下一个要访问的form item的提示语选定阶段也会被略过,即使该form item和前一个被选定的form item不是同一个。 |
|
<reprompt>元素在<catch>元素之外是不会起作用的。 |
|
七、GOTO |
|
<goto>元素用于: |
|
1、跳转到当前form的另一个form item; |
|
2、跳转到当前文档的另一个dialog; |
|
3、跳转到另一个文档。 |
|
要跳转到另一个form item,使用next属性,或使用expritem属性,如果该form item名可以通过ECMAScript表达式计算得到的话: |
|
<goto nextitem="ssn_confirm"/>
<goto expritem="(type==12)? 'ssn_confirm' : 'reject'"/>
|
|
要跳转到同一个文档的另一个dialog,使用next属性,或使用expr属性指定一个URI段: |
|
<goto next="#another_dialog"/>
<goto expr="'#' + 'another_dialog'"/>
|
|
要跳转到另一个文档使用next属性,或使用expr属性指定一个URI: |
|
<goto next="http://flight.example.com/reserve_seat"/>
<goto next="./special_lunch#wants_vegan"/>
|
|
URI可以是当前文档的绝对或相对的URI。要指定下一个文档开始的dialog,可以使用对应于该dialog的id属性值的URI段。如果没有指定URI段,则以要跳转到的文档的第一个dialog为开始的dialog。 |
|
注意,跳转到当前文档的另一个dialog会导致旧的dialog变量丢失,即使是一个dialog跳转到它自己也会丢失。同样的,使用相对或绝对的URI跳转到另一个文档,也会丢失文档变量,即使是一个文档跳转到它自己也会丢失。然而,当跳转到一个带有段标识符的空的URI引用时,文档变量不会丢失。例如下面两个语句在URI为http://someco.example.com/index.vxml的文档中有不同的行为: |
|
<goto next="#foo"/>
<goto next="http://someco.example.com/index.vxml#foo"/>
|
|
根据RFC2396,段标识符(“#”后面的部分)不是URI的一部分,到一个空的URI引用加上段标识符的跳转永远都不会获取到一个新的文档。因此,第一条语句中的“#foo”时一个带有段标识符的空的URI引用,它的文档变量不会丢失。在第二条语句中,“#foo”是一个绝对URI的一部分,该跳转会导致文档变量的丢失。如果想要在多文档中保存数据,请把数据保存在应用根文档中。 |
|
在<goto>元素的next或expr属性中,URI引用(详见RFC2396)指定要跳转到的dialog,如果这个URI引用包含一个绝对或相对的URI,该URI可以包含一个查询串,则FIA获取该URI,并且在目标文档中寻找相应的dialog。 |
|
如果该URI引用只包含一个段(即没有绝对或相对的URI),则没有任何文档被获取,FIA在当前文档中寻找相应的dialog。 |
|
URI引用中的段,如果有的话,以要跳转到的dialog命名,如果URI引用中没有段,则选定目标文档的第一个dialog。 |
|
如果要跳转到的form item、dialog或文档不可用(即该form item、dialog或文档不存在),必须抛出error.badfetch事件。注意,对于在dialog或文档跳转时出现错误,处理错误的作用域是依赖于平台的;对于在form item之间跳转时出现的错误,事件在dialog的作用域内处理。 |
|
<goto>元素的属性: |
next |
要跳转到的URI。 |
expr |
一个ECMAScript表达式 ,其结果值为要跳转到的URI。 |
nextitem |
当前form 中下一个要访问的form item名。 |
expritem |
一个 ECMAScript表达式,其结果值为当前form中下一个要访问的form item名。 |
fetchaudio |
见6.1节。它默认为fetchaudio <property>。 |
fetchhint |
见6.1节。它默认为documentfetchhint <property>。 |
fetchtimeout |
见6.1节。它默认为fetchtimeout <property>。 |
maxage |
见6.1节。它默认为documentmaxage <property>。 |
maxstale |
见6.1节。它默认为documentmaxstale <property>。 |
|
表47:<goto>元素的属性 |
|
必须正确地指定属性“next”、“expr”、“event”和“eventexpr”中的一个,否则会抛出error.badfetch事件。 |
|
八、SUBMIT |
|
<submit>元素用于提交信息给web服务器,然后跳转到web服务器响应后返回的文档。和<goto>元素不一样的是,<submit>元素可以通过HTTP GET或POST请求提交一个变量列表到文档服务器。例如可以提交一组form item变量到服务器: |
|
<submit next="log_request" method="post"
namelist="name rank serial_number"
fetchtimeout="100s" fetchaudio="audio/brahms2.wav"/>
|
|
<submit>元素的next或expr属性指定了要跳转到的dialog。该URI每次都要被获取,即使它只包含了一个段。在URI只包含一个段的情况下,请求的URI就是当前文档的基本URI。因此,下面的两个元素有完全不同的效果: |
|
<goto next="#get_pin"/>
<submit next="#get_pin"/>
|
|
注意:虽然URI总是要被获取,并且跳转到目标文档,但是通过缓存,还是能够满足某些<submit>元素请求的。例如,如果web服务器在响应时提供了一个显式的过期时间,就可能发生这种情况。 |
|
如果要跳转到的dialog或文档是非法的(即该dialog或文档不存在),必须抛出一个error.badfetch事件。注意:对于那些在dialog或文档跳转时出现的错误,在哪个作用域内处理它们是依赖于平台的。 |
|
<submit>元素的属性有: |
next |
要引用的URI。 |
expr |
ECMAScript表达式,它的结果值为要引用的URI。 |
namelist |
要提交的变量名列表。默认是提交所有有命名的input item。如果指定了namelist属性,它可以包含一个或多个变量名,以空格隔开。在VoiceXML和ECMAScript中声明的变量都能被提交。 |
method |
请求的方法:get(默认的)或post。 |
enctype |
被提交的文档的媒体编码类型,默认为application/x-www-form-urlencoded 。解释器也必须支持multipart/form-data ,也可以支持其他的编码类型。 |
fetchaudio |
见6.1节。它默认为fetchaudio <property>。 |
fetchhint |
见6.1节。它默认为documentfetchhint <property>。 |
fetchtimeout |
见6.1节。它默认为fetchtimeout <property>。 |
maxage |
见6.1节。它默认为documentmaxage <property>。 |
maxstale |
见6.1节。它默认为documentmaxstale <property>。 |
|
表48:<submit>元素的属性 |
|
必须正确的指定属性next或expr中的一个,否则会抛出error.badfetch事件。 |
|
当一个ECMAScript变量被提交给服务器时,它先被转换成一个字符串才被提交。VoiceXML目前还没有定义一种提交ECMAScript对象的机制,将来会定义这种机制。一种变通的方法是,开发者可以显式的提交对象的属性,例如“date.month date.year”。 |
|
如果<submit>元素包含的变量引用了一个录制的音频,但是没有包含multipart/form-data的ENCTYPE的话,VoiceXML目前还没有规定这种行为。试图在URI中对大量的数据编码显然是不合实际的。 |
|
九、EXIT |
|
<exit>把控制返回给解释器环境,由解释器环境决定下一步做什么。 |
|
<exit/>
|
|
该元素和<return>元素的不同之处在于它终止了所有加载的文档,而<return>则是从一个<subdialog>调用中返回。如果<subdialog>调用了一个新的文档(或应用),则<return>会终止被调用的文档,控制返回到<subdialog>元素继续执行。 |
|
注意,一旦<exit>把控制返回给解释器环境,解释器环境就可以做它想做的操作。例如,它可以给用户播放上一级<menu>元素中的提示语,或者挂机,或者把用户转接到人工坐席。 |
|
它的属性有: |
expr |
一个ECMAScript表达式,该表达式的值就是要返回的值(如“0”,“oops!”或“field1”)。 |
namelist |
要返回给解释器环境的变量名清单。默认是返回0个变量,这样意味着解释器环境将接收到一个空的ECMAScript 对象。 |
|
表49:<exit>元素的属性 |
|
可以正确地指定属性“expr”和“namelist”中的一个,否则,会抛出error.badfetch事件。 |
|
<exit>元素不会抛出一个“exit”事件。 |
|
十、RETURN |
|
<return>元素用于结束一个subdialog的执行,并把控制和数据返回给调用它的dialog。 |
|
它的属性有: |
event |
要返回并抛出的事件。 |
eventexpr |
ECMAScript表达式。其结果值为抛出的事件。它的作用是从subdiaolog中返回,并抛出该事件 。 |
message |
有关被抛出的事件的信息。在<catch>元素中,可通过“_message”变量取得该信息,见5.2.2节。 |
messageexpr |
ECMAScript表达式。其结果值为有关被抛出的事件的信息。 |
namelist |
要返回的变量名。默认为返回0个变量,即调用该subdialog的dialog将得到一个空的ECMAScript 对象 。 |
|
表50:<return>元素的属性 |
|
可以正确的指定属性“event”,“eventexpr”或“namelist”中的一个,否则会抛出一个error.badfetch事件。可以正确的指定属性“message”或“messageexpr”中的一个,否则会抛出一个error.badfetch事件。 |
|
当从一个subdialog中返回,一个事件在调用的地方被抛出,或者数据作为一个ECMAScript对象被返回,该对象的属性对应于subdialog中的<return>元素的namelist属性值。如果不是在subdialog中执行,却碰到<return>元素,则会抛出一个语义错误。 |
|
下面的例子展示了,当subdialog不能获得一个可识别的结果时,一个nomatch事件通过subdialog在调用它的dialog中抛出。 |
|
<?xml version="1.0" encoding="UTF-8"?>
<vxml version="2.0" xmlns="http://www.w3.org/2001/vxml"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.w3.org/2001/vxml
http://www.w3.org/TR/voicexml20/vxml.xsd">
<form>
<subdialog name="result" src="#getssn">
<nomatch>
<!-- a no match event that is returned by the subdialog indicates
that a valid social security number could not be matched. -->
<goto next="http://myservice.example.com/ssn-problems.vxml"/>
</nomatch>
<filled>
<submit namelist="result.ssn"
next="http://myservice.example.com/cgi-bin/process"/>
</filled>
</subdialog>
</form>
<form id="getssn">
<field name="ssn">
<grammar src="http://grammarlib/ssn.grxml" type="application/srgs+xml"/>
<prompt> Please say social security number.</prompt>
<nomatch count="3">
<return event="nomatch"/>
</nomatch>
<filled>
<return namelist="ssn"/>
</filled>
</field>
</form>
</vxml>
|
|
subdialog中的nomatch事件处理在第三次匹配失败时被触发,然后从subdialog中返回,并在调用他的dialog中抛出该事件。在这种情况下,调用的dialog将执行它自己的nomatch事件处理,通过<goto>元素跳转到另一个文档,而不是执行<filled>操作。在一般的情况下,如果得到一个识别结果,就会执行该<subdialog>元素中的<filled>操作,该识别结果可通过result.ssn访问。 |
|
十一、DISCONNECT |
|
它的作用是使解释器环境断开和用户之间的链接,此时,解释器环境将抛出connection.disconnect.hangup事件,它可以被捕获,以做一些清除的处理。 |
|
<disconnect/>
|
|
十二、SCRIPT |
|
<script>元素允许在VoiceXML脚本中使用一段客户端的脚本语言代码,它和HTML的<SCRIPT>元素类似。例如下面的例子中<script>元素用于计算一个数的阶乘: |
|
<?xml version="1.0" encoding="UTF-8"?>
<vxml version="2.0" xmlns="http://www.w3.org/2001/vxml"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.w3.org/2001/vxml
http://www.w3.org/TR/voicexml20/vxml.xsd">
<script> <![CDATA[
function factorial(n)
{
return (n <= 1)? 1 : n * factorial(n-1);
}
]]> </script>
<form id="form">
<field name="fact">
<nomatch>
<grammar type="application/srgs+xml" src="/grammars/number.grxml"/>
<prompt>
Tell me a number and I'll tell you its factorial.
</promptd>
<filled>
<prompt>
<value expr="fact"/> factorial is
<value expr="factorial(fact)"/>
</prompt>
</filled>
</field>
</form>
</vxml>
|
|
<script>元素可以出现在<vxml>元素和<form>元素中,或者出现在可执行的内容中(如<filled>,<if>,<block>,<catch>或<catch>元素的快捷标记)。在文档被装载后,<vxml>元素中的<script>元素和<var>元素都按照它们的文档顺序被依次求值。每次执行到<form>元素,该form中的<script>元素和<var>元素及form item 变量也是按照它们的文档顺序被依次求值。和其他的可执行元素一样,当在可执行的内容中碰到<script>元素时,都会执行它。 |
|
<script>元素的属性有: |
src |
如果脚本是外部的,则该属性指定了该外部脚本的URI。 |
charset |
属性src指定的脚本的字符编码。平台必须支持ISO/IEC 10646的UTF-8 和 UTF-16编码,也可以支持其他的编码,如IANA中定义的。默认为UTF-8。 |
fetchhint |
见6.1节。它默认为documentfetchhint <property>。 |
fetchtimeout |
见6.1节。它默认为fetchtimeout <property>。 |
maxage |
见6.1节。它默认为documentmaxage <property>。 |
maxstale |
见6.1节。它默认为documentmaxstale <property>。 |
|
表51:<script>元素的属性 |
|
必须指定一个src属性或一个联机脚本中的一个(不是两个都指定),否则,会抛出error.badfetch事件。 |
|
VoiceXML中的<script>元素没有type属性(这一点和HTML的<SCRIPT>元素不一样),ECMAScript是VoiceXML必须的脚本语言。
|
|
每个<script>元素在它的父元素的作用域内被执行,即它没有自己的作用域。例如在<script>元素用var语句声明的变量的作用域为该<script>元素的父元素(用ECMAScript的术语来说,就是"变量对象"为包含<script>元素的元素的当前作用域)。 |
|
下面的例子中<block>包含有<script>元素,并初始化该form中的一些变量: |
|
<?xml version="1.0" encoding="UTF-8"?>
<vxml version="2.0" xmlns="http://www.w3.org/2001/vxml"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.w3.org/2001/vxml
http://www.w3.org/TR/voicexml20/vxml.xsd">
<form>
<var name="hours"/>
<var name="minutes"/>
<var name="seconds"/>
<block>
<script>
var d = new Date();
hours = d.getHours();
minutes = d.getMinutes();
seconds = d.getSeconds();
</script>
</block>
<field name="hear_another">
<grammar type="application/srgs+xml" src="/grammars/boolean.grxml"/>
<prompt>
The time is <value expr="hours"/> hours,
<value expr="minutes"/> minutes, and
<value expr="seconds"/> seconds.
</prompt>
<prompt>Do you want to hear another time?</prompt>
<filled>
<if cond="hear_another">
<clear/>
</if>
</filled>
</field>
</form>
</vxml>
|
|
<script>元素的内容在和<var>元素一样的作用域内被求值(见5.1.2和5.3.1节)。 |
|
由于设置了ECMAScript的作用域链,因此,无论是<var>元素声明的变量,还是在<script>元素中声明的变量,它们的作用域都是包含该<var>元素或<script>元素的元素的作用域。例如,在<form>的<script>元素中声明的变量的作用域为dialog,它能够作为一个作用域为diaolog的变量被访问: |
|
<?xml version="1.0" encoding="UTF-8"?>
<vxml version="2.0" xmlns="http://www.w3.org/2001/vxml"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.w3.org/2001/vxml
http://www.w3.org/TR/voicexml20/vxml.xsd">
<form>
<script>
var now = new Date(); <!-- this has a dialog scope-->
</script>
<var name="seconds" expr="now.getSeconds()"/> <!-- this has a dialog scope-->
<block>
<var name="now" expr="new Date()"/> <!-- this has an anonymous scope -->
<script>
var current = now.getSeconds();<!-- "now" in the anonymous scope -->
var approx = dialog.now.getSeconds(); <!-- "now" in the dialog scope -->
</script>
</block>
</form>
</vxml>
|
|
所有的变量在被ECMAScript脚本或VoiceXML元素引用之前都必须声明,详见5.1.1节。 |
|
十三、LOG |
|
<log>元素让应用程序可以产生日志或调试信息,这些信息能够用来帮助开发者开发程序,或进行执行后的程序性能分析。 |
|
<log>元素可以包含文本(CDATA)和<value>元素的任意组合,产生的信息由文本和<value>元素的cond属性值串联起来组成。 |
|
信息的显示和记录方式是依赖于平台的,lable属性的用法也是依赖于平台的。 |
|
<log>元素中的ECMAScript表达式根据它们在文档中的顺序求值,使用<log>元素不应该对文档的解释产生任何的副作用。 |
|
<log>The card number was <value expr="card_num"/></log>
|
|
<log>元素的属性: |
label |
一个字符串,例如它可以用来表明该<log>元素的目的。 |
expr |
一个ECMAscript表达式,它的结果值为一个字符串。 |
|
表52:<log>元素的属性 |