<prompt bargein="true" timeout="3s"> This is the main menu. <break msecs="500"/> You can say product list to hear a list of products. <break msecs="500"/> You can say order status to check your order status. <break msecs="500"/> You can say frequently asked questions to get more information. <break msecs="500"/> You can always say main menu to return to this menu, or help for additional help. </prompt>
<grammar type="application/x-jsgf"> list product list | more information | frequently asked questions | questions | order status </grammar>
In order to keep track of the currently active form, the global variable form_pointer is set. This could be used to implement specific navigation logic, for example, by changing the behavior of a command slightly depending on where the command originated. Once the prompt has been played, and the user has responded with an utterance matching the inline grammar, the <filled> handler for this <field> is entered. This copies the value returned by the grammar to the global variable user_command, which is used by the navigator form to direct control flow to the required form. We could also use <subdialog> and pass a parameter, but this is simpler, and sufficient for this application.
Now our main menu form is finished, we can start to implement the dialogs that provide the application's basic functionality. First up is the orderStatus form that makes the most extensive use of dynamic content generation:
We need a test here to check that the customer does indeed have outstanding orders, and play a message to that effect:
<prompt bargein="true" timeout="1s"> <xsl:if test="count(/myrubberbands/customer_record/order_history/order) != 0"> This is a list of all your orders. </xsl:if> <xsl:if test="count(/myrubberbands/customer_record/order_history/order) = 0"> You have not placed any orders within the last thirty days. </xsl:if> <break msecs="500"/>
The next block creates a prompt for each order that was in the source XML document by using the XSLT element <xsl:for-each> to select XML elements that match the XPath in its attribute. The sayas attribute from the <order_date> element in our XML file is used here to provide an audio cue to identify the order to the user.
<xsl:for-each select="order_history/order"> <sayas class="date"> <xsl:value-of select="order_date/@sayas"/>, </sayas> you placed an order. Say order number <xsl:value-of select="position()"/> to hear more about it. <break msecs="500"/> </xsl:for-each> </prompt>
<grammar type="application/x-jsgf"> list | product list | more information | frequently asked questions | questions | order status |
The grammar also includes an option dynamically generated by the XSLT code. The user can say, "order number one" to access data on the first order in their list. This JSGF could be improved to accept shorter instructions, such as "order one", or even "one", but be aware that using "order number" followed by the number will help the ASR system correctly identify the user utterance, and will probably improve application performance in this situation.
In this chapter, all the grammars are inline, but XSLT could just as easily be used to create standalone external grammars in separate files, or to generate grammars in multiple formats (GSL, JSGF, XML) from a common data source, by the application of different stylesheets.
<xsl:for-each select="order_history/order"> order number <xsl:value-of select="position()"/> | </xsl:for-each> buy me </grammar>