Share via


Lesson 1 -- Building the First Document

In Lesson 1, we plan the structure of our travel agency application, work out a strategy for navigation, and build the basic entry-point document. The complete entry-point document, app-root.vxml, is listed at the end of the lesson.

This lesson is the longest in the tutorial, as it introduces all the requirements and concepts needed to create our basic entry-point document. By the end of this first lesson you will have a VoiceXML document that prompts the caller to make, change, or cancel a reservation and decides what to do next, based on the caller's response. You can test this document in the Tellme Studio Scratchpad.

Subsequent lessons build on this lesson's document and add functionality.

Application Structure

The caller to our travel agency application has several basic choices. The Contoso Travel Agency has determined that callers should be able to handle the following tasks:

  • Make a new reservation for one, two, or all three of a plane, hotel, or rental car (seven choices).

  • Change (including cancel) a reservation for one, two, or all three of a plane, hotel, or rental car (seven choices).

  • Get a restaurant recommendation in a particular city.

In order to design the application so that a caller can accomplish the above tasks, we will design the application to have ten separate documents:

  1. What do you want to do? (entry-point document)

  2. Make a new plane reservation.

  3. Make a new hotel reservation.

  4. Make a new rental car reservation.

  5. Look up an existing reservation.

  6. Change a plane reservation.

  7. Change a hotel reservation.

  8. Change a rental car reservation.

  9. Get a restaurant recommendation.

  10. Pay by credit card.

In this first document, all we want to do is to learn which task the caller wants to accomplish.

The entry-point document (app-root.vxml)

The dialogs in this document ask callers what they want to do:

  • Do they want to make a new reservation or modify an existing one?

  • What reservations? A reservation can be for one, two, or all three of a flight, a hotel, or a rental car (seven alternatives).

  • Do they want restaurant recommendations?

We can use two forms (dialogs) in this entry-point document:

  1. A form that asks whether the caller wants to make a new reservation, change an existing reservation, or find a restaurant. We will name this form main.

  2. A form for new reservations that asks which type: flight, hotel, or car. The caller can choose one, two, or three types. We will name this form new_reservation.

Let's just dive in.

VoiceXML document framework

VoiceXML files are XML documents with a .vxml suffix.

We begin our document with a standard XML declaration:

<?xml version="1.0" encoding="UTF-8"?>

The root element in a VoiceXML document is <vxml>. It has a number of possible attributes (see https://studio.tellme.com/vxml2/ref/elements/vxml.html), three of which we are going to use immediately:

  1. xmlns. This is the XML namespace, required for all VoiceXML documents, which must be xmlns=http://www.w3.org/2001/vxml.

  2. version. The VoiceXML version number is required for all VoiceXML documents and must be 2.1 for the Tellme platform using the Microsoft speech engine.

  3. xml:lang. The language identifier, which should be US English (en-US). This attribute is not required, as it is the default for the Tellme platform, but we are going to include it in all our documents for reasons that will become clear later.

All XML documents must have a root element that contains all the other elements in the document. For VoiceXML, the root element is <vxml>. You can think of it as a container for dialogs since that is what a VoiceXML document is, a collection of dialogs. There are two types of dialogs: forms and menus. We have already discussed forms in the introduction. Menus, by comparison, are shorthand substitutes for forms that present the caller with a list of choices and then transition to another dialog based on that choice.

Note

Menus can be a bit simpler than forms and can require a bit less code. However, forms can be used to accomplish the same thing and are much more flexible. As a result, most VoiceXML developers prefer forms to menus. We will introduce the <menu> element in Lesson 3, just so you know how they work, but we are not going to use menus in the application we are developing.

Forms can contain zero, one, or more <field> elements. Forms that contain a number of fields that are executed in order are called "directed forms." The application we are developing in this tutorial, like many VoiceXML applications, uses directed forms.

When a form contains two or more fields that do not have to be executed in order, it is called a "mixed-initiative" form. In such forms all of the grammars are active simultaneously and the application listens for responses to all of the fields at once. The fields can be filled in any order and the form must contain logic to make sure that all the fields are filled. We will develop a mixed initiative dialog in Lesson 10 to demonstrate how they work.

So, the framework for our document is:

<?xml version="1.0" encoding="UTF-8"?>
<vxml xmlns="http://www.w3.org/2001/vxml" 
      version="2.1" 
      xml:lang="en-US">
....
<form id="main">
   <field name="main_selection">........</field>
</form>
<form id="new_reservation">
   <field name="new_reservation_type">........</field>
</form>
</vxml>

Important

When a VoiceXML application is first deployed, there is a period of testing during which the application is "tuned" (optimized). To facilitate tuning, field names should be human-readable and unique across all documents in an application.

Each <field> element will include <prompt>, <grammar>, and <filled> elements. For the purposes of this lesson, our prompts will use text to speech (TTS). However, if this were a live commercial application for real callers, we might choose to record prompts using professionals (called "voice talent" in the industry.

Note

Whenever text is placed in a <prompt> element, the VoiceXML interpreter automatically renders it as TTS.

The entry-point document's forms

Let's start with the main_selection field:

<field name="main_selection">
<prompt>
   Welcome to Contoso Travel. Say new reservation, change
   reservation, or restaurant recommendation.
</prompt>
<grammar version="1.0" root="top">
   <rule id="top">
      <one-of>
         <item>new reservation</item>
         <item>change reservation</item>
         <item>restaurant recommendation</item>
      </one-of>
   </rule>
</grammar>
<filled>
   <!-- need logic here to transition to the appropriate next
        form -->
</filled>
</field>

The attributes of the <grammar> element that we are including here are minimal (there are many more possible attributes; see https://studio.tellme.com/vxml2/ref/elements/grammar.html).

  • The version attribute (required by VoiceXML) states that the SRGS 1.0 standard is met.

  • The root attribute (required by the Tellme platform) identifies the principal <rule> element (the one to use first). Note that the root attribute of a grammar has nothing to do with a "root" document.

Note

We are not using the mode attribute (voice or dtmf) because our grammar is a voice grammar and voice is the default for mode. When the mode is voice, the language must be named. We do not need to specify the language here, however, because we named it in the <vxml> attributes (xml:lang="en-US"). The <grammar> element inherits the language attribute from the <vxml> element. We used the xml:lang attribute in the <vxml> element deliberately so we do not have to use it in our <grammar> elements.

Logic in the <filled> element of the main_selection field will do the following:

  • If the caller's response is "new reservation" the form will transition to the new_reservation form in this same document, which is shown below.

  • If the caller's response is "change reservation", the form will transition to a new document (change-reservation.vxml) where the caller will be prompted for his or her reservation number. The application will retrieve the reservation or reservations from the travel agency's database and ask the caller what they want to change.

  • If the caller's response is "restaurant recommendation", the form will transition to a new document (restaurant.vxml) where the caller will be prompted for the name of a city and culinary preferences. Recommendations will then be pulled from a database.

Note

Making a new reservation and changing an existing reservation can't be handled easily by the same document. In the case of changing a reservation, the agency already has data about the caller, some or all of which needs to be updated.

Here is a first version of the new_reservation form in app-root.vxml:

   <form id="new_reservation">
<field name="new_reservation_type">
<prompt>
   What type of reservation do you want to make? Say plane,
   hotel, or car. You can combine types by saying
   plane and hotel for example
</prompt>
<grammar version="1.0" root="top">
   <rule id="top">
      <one-of>
         <item>plane</item>
         <item>hotel</item>
         <item>car</item>
         <item>plane and hotel</item>
         <item>hotel and car</item>
         <item>plane and car</item>
         <item>plane and hotel and car</item>
      </one-of>
   </rule>
</grammar>
<filled>
   <!-- need logic here to transition to the appropriate next
        form -->
</filled>
</field>
   </form>

Note

: The prompt is too wordy. We'll fix it later in Lesson 4. Also, the grammar does not allow the caller to say anything other than exactly what we tell them to say. For example, we tell them to say "plane and hotel" but don’t allow them to say "hotel and plane." This is unrealistic. We will enhance the grammar so that it is more flexible at the same time we fix the prompt.

We will need to add logic in the <filled> element that does the following:

If the caller's response is:

Transitions to:

Then, later, transitions to:

plane

a new document for plane reservations

--

hotel

a new document for hotel reservations

--

rental car

a new document for car reservations

--

plane and hotel

a new document for plane reservations

a new document for hotel reservations

plane and rental car

a new document for plane reservations

a new document for car reservations

hotel and rental car

a new document for hotel reservations

a new document for car reservations

plane and hotel and rental car

a new document for plane reservations

a new document for hotel reservations, and after that, to a new document for car reservations

When making reservations of several different types, the application handles the reservations in this order: plane, hotel, rental car.

Transitions are specified in the <filled> element by using the <goto> element, transitioning the logic to a different form or even a different VoiceXML document.

Uh-oh, we have a problem

When a caller wants to make several types of reservations, we start with making a plane reservation. To do this, the application uses the <goto> element to transition to a document for making plane reservations.

Here's the problem: The application can only make one reservation at a time, but it must remember that there is another reservation to handle when it is finished with the first one. When the plane reservation dialog is finished, the application should transition to the document for the next type of reservation. But how does the plane reservation document know that a transition should be made and where the transition should go?

The <goto> element does not have any mechanism to tell the next form or document what it should do when it is finished.

This problem would be solved if there were variables telling the application all the things that need to be done. How then is the plane reservation document (or any other document) to obtain such variables?

The solution to this problem is to use a "root document." Root documents can contain variables that are visible to all the other documents in the application.

Note

Once again, root documents have nothing to do with the root rule of a grammar.

In a root document we can have a set of variables that determines all the things that need doing. For example, consider this set of variables:

doPlaneReservation, set to true

doHotelReservation, set to false

doCarReservation, set to true

If these variables are visible to all the documents in the application, then it is known everywhere that the application is supposed to make both a plane reservation and a rental car reservation, but not a hotel reservation. Then, when the plane reservation is finished with its task, it can check the variable list and see that it should transition to the car rental reservation document.

So we need to back up and learn about:

  • Transitions.

  • Variables.

  • Root documents.

Transitions

A caller is always in one conversational state, or form, at a time. Each form determines the next form to transition to. Transitions are executed with the <goto> element specifying the URI that defines the next document and form to use. If the URI does not refer to a document, the current document is assumed. If it does not refer to a form, the first form in the document is assumed.

Important

Execution of the application is terminated when a form does not specify a transition to another form, or if it has an element that explicitly exits the conversation.

Variables

VoiceXML can declare variables, assign values to them, and change their values. It is also possible to perform these same operations with JavaScript in a <script> element. Variables created with JavaScript are completely interchangeable with variables created in the VoiceXML code. You can use or modify the same variable in either VoiceXML code or JavaScript, no matter whether it was originally created in VoiceXML code or in JavaScript.

Variable names can consist of numbers, letters, the underscore ('_'), and the dollar sign ('$'). They must begin with a letter and can only terminate with a number, letter, or underscore.

VoiceXML variables

VoiceXML variables can be declared in <vxml>, <form>, and a number of other elements. To declare a variable and assign it a value in VoiceXML code, use the <var> element. Here is an example of declaring a variable named doHotelReservation and assigning it the value false.

<var name="doHotelReservation" expr="false"/>.

The name attribute sets the name of the variable and the expr attribute sets its value. You can also declare a variable without setting its value.

You can assign a new value to a declared variable with VoiceXML's <assign> element, as follows:

<assign name="doHotelReservation" expr="true"/>.

After this assignment, the value of doHotelReservation is true.

Important

You cannot always change the value of a variable in the same elements where you can declare it. For example, while you can use the <var> element in the <vxml> or <form> elements, you cannot use the <assign> element in either of these two elements.

Tip

The Tellme Studio elements catalog (https://studio.tellme.com/vxml2/ref/elements/) is an important resource for a VoiceXML developer. For example, it will help you figure out where you can use the <assign> element. Let's say you are writing code in a <form> element and you want to use the <assign> element to change the value of a variable, but you aren't sure if you can use <assign> in a <form> element (you can't).

If you look at the catalog entry for <form>, you see that its list of children does not include <assign> so you cannot use it. Looking at the catalog entry for <assign>, you see that its parents can include the <block> element. Looking at the <block> element, you see that its only parent is <form>. So, you can use <assign> in a <form> element after all-you just have to enclose it in a <block> element.

Thus, you learn that this doesn't work

<form> <assign........../> </form>

But this does work:

<form> <block> <assign........../> </block> </form>

JavaScript variables

You must enclose JavaScript in <script>....</script> tags. Legal parents for <script> elements include <vxml>, <form>, <block>, <filled>, and a number of others.

Since the JavaScript in a VoiceXML document is parsed by an XML parser, you cannot use any symbols that are reserved for XML, such as '<', unless you enclose the JavaScript in a CDATA section or use entities. It is a good idea to enclose the JavaScript in a CDATA section in all cases, whether or not you include reserved symbols. Throughout this tutorial, we enclose JavaScript like this:

<script> <![CDATA[
       <!-JavaScript statements go here -->
]]> </script>

To declare a variable and assign it a value in JavaScript, simply write, for example:

var doHotelReservation = false;

To change the value of an existing variable, simply write:

doHotelReservation = true;

With JavaScript, you can declare a variable, assign it an initial value, or change its value anywhere in the VoiceXML code that a <script> element is legal.

Referencing variables

In VoiceXML, you reference a variable using the <value> element. Here is an example. Assume that "Dallas" is the value of a variable named match_response. Then, consider this prompt:

<prompt>
   I think I heard you say <value expr="match_response"/>
</prompt>

The TTS delivered is "I think I heard you say Dallas."

In JavaScript, by comparison, you reference the value of a variable simply by using its name.

Legal parent elements for the <value> element are: <audio>, <block>, <catch>, <emphasis>, <enumerate>, <error>, <field>, <filled>,<foreach>, <help>, <if>, <initial>, <log>, <menu>, <noinput>, <nomatch>, <object>, <p>, <prompt>, <prosody>, <record>, <s>, <say-as>, <subdialog>, <transfer>, and <voice>.

Legal parents for the <script> element (where you can reference the VoiceXML variables as JavaScript variables) are: <block>, <catch>, <error>, <filled>, <foreach>, <form>, <help>, <if>, <menu>, <noinput>, <nomatch>, <prompt>, and <vxml>.

While most of these elements do not mean anything to you at this point, comparison of the two lists shows that you can reference VoiceXML variables using the <value> element within many more VoiceXML elements than you can with JavaScript. The following table shows the differences:

VoiceXML elements where you can reference variables with <value> elements but not with <script> elements

VoiceXML elements where you can reference variables with <script> elements but not with <value> elements

VoiceXML elements where you can reference variables with both <script> elements and <value> elements

<audio>, <emphasis>, <enumerate>, <field>, <initial>, <log>, <object>, <p>, <prosody>, <record>, <s>, <say-as>, <subdialog>, <transfer>, <voice>

<form>, <vxml>

<block>, <catch>, <error>, <filled>, <foreach>, <help>, <if>, <menu>, <noinput>, <nomatch>, <prompt>

Root documents

A VoiceXML application can consist of one or many documents. Documents are linked to other documents through URIs.

Important

In cases where you want multiple documents to work together as one application, you can select one document to be the "root document," and the rest to be "leaf documents" (a root document is not required in multiple-document applications, though). When there is a root document, each leaf document names the root document in the application attribute of its <vxml> element. For example,

<vxml xmlns="http://www.w3.org/2001/vxml" version="2.1" 
      application="app-root.vxml">

When this is done, every time the interpreter is told to load and execute a leaf document in the application, it first loads the application root document (if it is not already loaded). Thus, one of the following two conditions always holds during execution:

  • The application root document is loaded and execution is occurring there. There is no leaf document.

  • The application root document and a single leaf document are both loaded and execution is occurring in the leaf document.

While the root document is loaded (it always is), its variables are available to the other documents as application variables. If the root document contains grammars, they may also remain active throughout the application.

We will use the document that we have presciently named app-root.vxml as the root document in this tutorial.

Note

Remember that a root document has nothing to do with a root rule in a grammar.

Document URIs

All of the documents used in the first part of this tutorial except app-root.vxml are stored in https://studio.tellme.com/vxml-tutorial. They are:

https://studio.tellme.com/vxml-tutorial/change-reservation.vxml

hthttps://studio.tellme.com/vxml-tutorial/new-plane.vxml

https://studio.tellme.com/vxml-tutorial/new-hotel.vxml

https://studio.tellme.com/vxml-tutorial/new-car.vxml

https://studio.tellme.com/vxml-tutorial/restaurant.vxml

Note

app-root.vxml is not stored with the other documents because it changes throughout the basic tutorial and we want to run the various changed versions in the Tellme Studio Scratchpad.

What's in the leaf documents?

For the basic tutorial, all of the leaf documents are read-only and have minimal content. They simply tell you what document you transitioned to and then exit (they exit because there is no transition to a successor document or form). For example, this is the new-plane.vxml file:

<?xml version="1.0" encoding="UTF-8"?>
<vxml xmlns="http://www.w3.org/2001/vxml" version="2.1" 
                                application="app-root.vxml">
<form>
   <block>
      <prompt>
         You have entered the new plane reservation document
      </prompt>
   </block>
</form>
</vxml>

We are not going to develop these files further. We just want them to exist so we can test the logic in app-root.vxml that transitions to them.

Two more <vxml> attributes

We are going to start using two more attributes of the <vxml> element:

  • xml:base

  • application

xml:base

For convenience, we will start using the <vxml> attribute, xml:base. It will be:

xml:base="https://studio.tellme.com/vxml-tutorial/"

This attribute will appear in all of our .vxml documents to save us from having to enter a complete path every time we want to reference one of the documents.

Then, to reference a document in our application, we just use URI="filename". For example, URI="app-root.vxml".

Using the xml:base attribute saves us from having to write the full URI, https://studio.tellme.com/vxml-tutorial/app-root.vxml

application

Since we want to use a root document, we must also use the <vxml> attribute, application, in other documents. This is the attribute that identifies the root document in our application to all the leaf documents. It will be application="app-root.vxml"

This attribute should be in all of our .vxml files, except app-root.vxml. That is, it defines the root document for each of the leaf documents, but not for the root document itself.

Root document variables

The main reason we want to use a root document is to have variables that are visible to all the documents in the application. These variables must tell all the documents what tasks have been requested by the caller. For simplicity, let us declare all these variables and assign them initial values using JavaScript. They will go in a <script> element, like this:

<script> <![CDATA[
   var doNewPlaneRes = false;
   var doNewHotelRes = false;
   var doNewCarRes = false;
    var doChangePlaneRes = false;
   var doChangeHotelRes = false;
   var doChangeCarRes = false;
   var doRestaurantRec = false;
]]> </script>

These variables could also have been declared like this:

   <var name="doNewPlaneRes" expr="false"/>
   <var name="doNewHotelRes" expr="false"/>
   <var name="doNewCarRes" expr="false"/>
   <var name="doChangePlaneRes" expr="false"/>
   <var name="doChangeHotelRes" expr="false"/>
   <var name="doChangeCarRes" expr="false"/>
   <var name="doRestaurantRec" expr="false"/>

The application begins with all the variables set to false. When the caller requests an option, the variable will be set to true.

Current version of the entry-point document (app-root.vxml)

Putting together everything we have discussed so far, we have:

<?xml version="1.0" encoding="UTF-8"?>
<vxml xmlns="http://www.w3.org/2001/vxml"
      version="2.1"
      xml:lang="en-US"
      xml:base="https://studio.tellme.com/vxml-tutorial/">
      
   <script> <![CDATA[
         var doNewPlaneRes = false;
         var doNewHotelRes = false;
         var doNewCarRes = false;
         var doChangePlaneRes = false;
         var doChangeHotelRes = false;
         var doChangeCarRes = false;
         var doRestaurantRec = false;
      ]]> </script>

   <form id="main">
      <field name="main_selection">
         <prompt>
            Welcome to Contoso Travel. Say new reservation, change
                             reservation, or restaurant recommendation.
         </prompt>
         <grammar version="1.0" root="top">
            <rule id="top">
               <one-of>
                  <item>new reservation</item>
                  <item>change reservation</item>
                  <item>restaurant recommendation</item>
               </one-of>
            </rule>
         </grammar>
         <filled>
            <!-- need logic here to transition to the appropriate 
                 next form -->
         </filled>
      </field>
   </form>
   <form id ="new_reservation">
      <field name="new_reservation_type">
         <prompt>
            What type of reservation do you want to make? Say plane, hotel,
            or car. You can combine types by saying plane and hotel for
            example.
         </prompt>
         <grammar version="1.0" root="top">
            <rule id="top">
               <one-of>
                  <item>plane</item>
                  <item>hotel</item>
                  <item>car</item>
                  <item>plane and hotel</item>
                  <item>hotel and car</item>
                  <item>plane and car</item>
                  <item>plane and hotel and car</item>
               </one-of>
            </rule>
         </grammar>
         <filled>
            <!-- need logic here to transition to the appropriate 
                 next form -->
         </filled>
      </field>
   </form>
</vxml>

Adding the <filled> logic

We need to put content in the <filled> elements of the app-root.vxml document that tells the VoiceXML interpreter where to transition to. Transitioning requires knowing what the caller's response to the field's prompt was.

Important

When a match occurs between the caller's response and one of the grammar's choices in a field, the VoiceXML interpreter assigns the value of the matched choice to a variable with its name specified by the name attribute of the <field> element. For example, in the main form above, the field name is main_selection. If the caller says "new reservation," this will match one of the field's grammar choices and set the value of the main_selection variable to "new reservation".

The main_selection field

We will use the value of the main_selection variable to decide what the transition destination named in the <filled> element should be.

If the caller's response is:

Transition to:

new reservation

the form with id= "new_reservation" in this same document.

change reservation

the document named change-reservation.vxml

restaurant recommendation

the document named restaurant.vxml

Transitions are made with the <goto> element. The destination of the transition is expressed as an attribute of <goto> (see https://studio.tellme.com/vxml2/ref/elements/goto.html). There are several different attributes one can use. We are going to use the expr attribute-its value must be a valid JavaScript expression that evaluates to the URI of a document, dialog, or both. A string is a valid JavaScript expression, and that is what we will use.

We use JavaScript to create the <goto> destination as a string:

  1. First, we declare a variable named next_destination with an empty string as its initial value.

  2. Then we use a switch statement (we could have used an if...else if...else statement instead) to determine what the transition destination of main_selection should be, based on the caller's response.

  3. Finally, we use the <goto> element with an expr attribute that names the transition destination (next_destination).

Important

If the next_destination string is a file name, the VoiceXML interpreter adds the xml:base string as its path. If the string is not a file name (i.e., does not have a .vxml suffix), the xml:base path is not added.

You use the "fragment" operator ('#') to specify a form in the current document as a transition destination. If we want to transition to the new_reservation form, the value of the <goto> expr attribute should be #new_reservation. Since this is not a file name, the xml:base path is not prefixed.

With the <filled> element's logic included, the main form looks like this:

<form id="main">
      <field name="main_selection">
         <prompt>
            Welcome to Contoso Travel. Say new reservation, change
                             reservation, or restaurant recommendation.
         </prompt>
         <grammar version="1.0" root="top">
            <rule id="top">
               <one-of>
                  <item>new reservation</item>
                  <item>change reservation</item>
                  <item>restaurant recommendation</item>
               </one-of>
            </rule>
         </grammar>

         <filled>
            <script> <![CDATA[
                  var next_destination = "";
                  switch (main_selection){

                  case "new reservation" :
                    next_destination = "#new_reservation";
                    break;
                    
                  case "change reservation" :
                    next_destination = "change-reservation.vxml";
                    break;
                    
                  case "restaurant recommendation" :
                    next_destination = "restaurant.vxml";
                    break;
                    
                  default:
                    next_destination = "error.vxml";
                    break;
                 }
               ]]> </script>
            <goto expr="next_destination"/>
         </filled>
      </field>
   </form>

The new_reservation form

We will use the value of the new_reservation_type variable to decide what the transition destination named in the <filled> element should be.

If the caller's response is:

Transition to this document:

Set these variables to true:

plane

new-plane.vxml

--

hotel

new-hotel.vxml

--

rental car

new-car.vxml

--

plane and hotel

new-plane.vxml

doNewHotelRes

plane and rental car

new-plane.vxml

doNewCarRes

hotel and rental car

new-hotel.vxml

doNewCarRes

plane and hotel and rental car

new-plane.vxml

doNewHotelRes, doNewCarRes

Note

We don't need to use the doNewPlaneRes variable because we always do the plane reservation first.

We use a switch statement again. The main differences from the switch statement used previously are:

  • There are more choices (seven in all).

  • In some cases we need to set the variables that tell the application that there is another transition to be done after the first transition is finished.

Here is the code:

<form id="new_reservation">
      <field name="new_reservation_type">
         <prompt>
            What type of reservation do you want to make? Say plane, hotel,
            or car. You can combine types by saying plane and hotel for
            example.
         </prompt>
         <grammar version="1.0" root="top">
            <rule id="top">
               <one-of>
                  <item>plane</item>
                  <item>hotel</item>
                  <item>car</item>
                  <item>plane and hotel</item>
                  <item>hotel and car</item>
                  <item>plane and car</item>
                  <item>plane and hotel and car</item>
               </one-of>
            </rule>
         </grammar>

         <filled>
            <script> <![CDATA[
                  var next_destination = "";
                  switch (new_reservation_type){

                  case "plane" :
                    next_destination = "new-plane.vxml";
                    break;

                  case "hotel" :
                    next_destination = "new-hotel.vxml";
                    break;

                  case "car" :
                    next_destination = "new-car.vxml";
                    break;
                    
                  case "plane and hotel" :
                    next_destination = "new-plane.vxml";
                    doNewHotelRes = true;
                    break;

                  case "plane and car" :
                    next_destination = "new-plane.vxml";
                    doNewCarRes = true;
                    break;

                  case "hotel and car" :
                    next_destination = "new-hotel.vxml";
                    doNewCarRes = true;
                    break;
                    
                  case "plane and hotel and car" :
                    next_destination = "new-plane.vxml";
                    doNewHotelRes = true;
                    doNewCarRes = true;
                    break;

                  default:
                    next_destination = "error.vxml";
                    break;
                 }
               ]]> </script>

            <goto expr="next_destination"/>
         </filled>
      </field>
   </form>

The final Lesson 1 application (app-root.vxml)

Putting it all together, we have a complete, functioning application. We will add more complexity in future lessons. For the moment, we're keeping it simple.

This version of app-root.vxml (and subsequent versions in this tutorial) has no logic to deal with situations where the caller wants to change a reservation or get a restaurant recommendation. That logic would be in in the relevant leaf documents (which we are not going to develop further).

You can copy this application, paste it into Tellme Studio Scratchpad, and run it.

Note

A <catch event="noinput nomatch"> element has been introduced into each of the two fields (in bold font). This is necessary to handle situations where the speech recognition engine doesn't hear or understand what the caller said. Without this code, the application would exit if the caller was silent or said the wrong thing. "Event handlers," of which this <catch> element is one, will be discussed in Lesson 8. We will include <catch event="noinput nomatch"> elements in all or our code, without any explanation prior to Lesson 8.

<?xml version="1.0" encoding="UTF-8"?>
<vxml xmlns="http://www.w3.org/2001/vxml"
      version="2.1"
      xml:lang="en-US"
      xml:base="https://studio.tellme.com/vxml-tutorial/">
      
   <script> <![CDATA[
         var doNewPlaneRes = false;
         var doNewHotelRes = false;
         var doNewCarRes = false;
         var doChangePlaneRes = false;
         var doChangeHotelRes = false;
         var doChangeCarRes = false;
         var doRestaurantRec = false;
      ]]> </script>

   <form id="main">
      <field name="main_selection">
         <prompt>
            Welcome to Contoso Travel. Say new reservation, change
                             reservation, or restaurant recommendation.
         </prompt>
         <grammar version="1.0" root="top">
            <rule id="top">
               <one-of>
                  <item>new reservation</item>
                  <item>change reservation</item>
                  <item>restaurant recommendation</item>
               </one-of>
            </rule>
         </grammar>

         <catch event="noinput nomatch">
            Sorry. Didn't get that. Please try again.
            <reprompt/>
         </catch>

         <filled>
            <script> <![CDATA[
                  var next_destination = "";
                  switch (main_selection){

                  case "new reservation" :
                    next_destination = "#new_reservation";
                    break;
                    
                  case "change reservation" :
                    next_destination = "change-reservation.vxml";
                    break;
                    
                  case "restaurant recommendation" :
                    next_destination = "restaurant.vxml";
                    break;
                    
                  default:
                    next_destination = "error.vxml";
                    break;
                 }
               ]]> </script>
            <goto expr="next_destination"/>
         </filled>
      </field>
   </form>
   <form id ="new_reservation">
      <field name="new_reservation_type">
         <prompt>
            What type of reservation do you want to make? Say plane, hotel,
            or car. You can combine types by saying plane and hotel for
            example.
         </prompt>
         <grammar version="1.0" root="top">
            <rule id="top">
               <one-of>
                  <item>plane</item>
                  <item>hotel</item>
                  <item>car</item>
                  <item>plane and hotel</item>
                  <item>hotel and car</item>
                  <item>plane and car</item>
                  <item>plane and hotel and car</item>
               </one-of>
            </rule>
         </grammar>

         <catch event="noinput nomatch">
            Sorry. Didn't get that. Please try again.
            <reprompt/>
         </catch>

         <filled>
            <script> <![CDATA[
                  var next_destination = "";
                  switch (new_reservation_type){

                  case "plane" :
                    next_destination = "new-plane.vxml";
                    break;

                  case "hotel" :
                    next_destination = "new-hotel.vxml";
                    break;

                  case "car" :
                    next_destination = "new-car.vxml";
                    break;
                    
                  case "plane and hotel" :
                    next_destination = "new-plane.vxml";
                    doNewHotelRes = true;
                    break;

                  case "plane and car" :
                    next_destination = "new-plane.vxml";
                    doNewCarRes = true;
                    break;

                  case "hotel and car" :
                    next_destination = "new-hotel.vxml";
                    doNewCarRes = true;
                    break;
                    
                  case "plane and hotel and car" :
                    next_destination = "new-plane.vxml";
                    doNewHotelRes = true;
                    doNewCarRes = true;
                    break;

                  default:
                    next_destination = "error.vxml";
                    break;
                 }
               ]]> </script>

            <goto expr="next_destination"/>
         </filled>
      </field>
   </form>
</vxml>

What's next?

In this lesson we have planned the structure of our travel agency application, worked out a strategy for navigation, and built the basic entry-point document.

We have learned all the basic requirements and concepts needed to create a first working version of Contoso Travel's entry-point document. This document prompts the caller to make or change a reservation, or ask for a restaurant recommendation, and decides what to do next, based on the caller's response.

The version of app-root.vxml developed in this lesson responds only to voice input from the caller. In Lesson 2, we will add DTMF capability. That is, we will enable app-root.vxml to allow the caller to respond to prompts using the touch-tone phone keys as well as speaking.