topbartopbar
SALT AND VoiceXML VOICE-ONLY EXAMPLES

Introduction

Here are six examples of SALT and VoiceXML being used in voice-only applications. The SALT examples are all from the SALT 1.0 specifications and similar sources. Two SALT examples have small bits of visual interface in them, which we identify with grey italic font.


Transitioning to a New Page
Stock Ordering
Entering a PIN
Recording a Greeting
Entering a From City and To City ("Unsafely")
Entering a From City and To City ("Safely")

SALT Forum Companies Back VoiceXML

Transitioning to a New Page

The transition.salt and transition.vxml pair show how to go to a new page in each markup language.

<html xmlns:salt="http://www.saltforum.org/2002/SALT" >
  <body>
    <form id="form1" action="nextpage.html">
      <input type="button" onclick="transition();" value="go to next page" />
    </form>
    <salt:prompt id="transitionPrompt">
      Let's go to the next page!
    </salt:prompt>
    <script>
      function transition()
      {
        transitionPrompt.Queue();
        PromptQueue.Start();
        form1.submit();
      }
    </script>
  </body>
</html>

 

<?xml version="1.0"?>
<vxml version="2.0" xmlns="http://www.w3.org/2001/voice">
  <form>
    <block>
      Let's go to the next page!
      <goto next="nextpage.vxml"/>
    </block>
  </form>
</vxml>

Figure 2: transition.vxml

 

Stock Ordering

The next example is a four-field stock ordering form.  Even though the SALT is very nicely written, it is nearly four times the size of the equivalent VoiceXML, because the SALT author had to write an FIA while the VoiceXML author gets one for free.  Note that the SALT example has some visual elements that a pure voice dialog would not need (page title, field titles).  On the other hand, it has an artificially compact help message generation function that doesn't generate useful help messages.

<html xmlns:salt="http://www.saltforum.org/2002/SALT"> 
    <title>Context Sensitive Help</title> 
      <head>
            <script>
            <![CDATA[
            var focus;
            function RunSpeech()
            {
                if (trade.stock.value == "") {
                    focus="trade.stock";
                    p_stock.Start();
                    return;
                }
                if (trade.op.value == "") {
                    focus="trade.op";
                    p_op.Start();
                    return;
                }
                if (trade.quantity.value == "") {
                    focus="trade.quantity";
                    p_quantity.Start();
                    return;
                }
                if (trade.price.value == "") {
                    focus="trade.price";
                    p_price.Start();
                    return;
                }
            }
            function handle()
            {
                res = event.srcElement.recoresult;
                if (res.value == "help") {
                    text = "Please just say ";
                    text += document.all[focus].title;
                    p_help.Start(text);
                } else {
                // proceed with value assignments
                }
            }
            ]]>
        </script>
    </head>
    <body onload="RunSpeech()">
        <salt:prompt id="p_help" oncomplete=" RunSpeech()" />
        <salt:prompt id="p_stock" oncomplete="g_stock.Start()">
            Please say the stock name
        </salt:prompt>
        <salt:prompt id="p_op" oncomplete="g_op.Start()">
            Do you want to buy or sell
        </salt:prompt>
        <salt:prompt id="p_quantity" oncomplete="g_quantity.Start()">
            How many shares?
        </salt:prompt>
        <salt:prompt id="p_price" oncomplete="g_price.Start()">
            What's the price
        </salt:prompt>

        <salt:listen id="g_stock" onreco="handle(); RunSpeech()">
            <salt:grammar src="./g_stock.grxml" />
        </salt:listen >
        <salt:listen id="g_op" onreco="handle(); RunSpeech()">
            <salt:grammar src="./g_op.grxml" />
        </salt:listen >
        <salt:listen id="g_quantity" onreco="handle(); RunSpeech()">
            <salt:grammar src="./g_quant.grxml" />
        </salt:listen >
        <salt:listen id="g_price" onreco="handle();RunSpeech()"> 
            <salt:grammar src="./g_quant.grxml" />
        </salt:listen >
        <form id="trade">
            <input name="stock" title="stock name" />
            <select name="op" title="buy or sell">
                <option value="buy" />
                <option value="sell" />
            </select>
			      <input name="quantity" title="number of shares" />
            <input name="price" title="price" />
        </form>
    </body>
</html>
Figure 3: stock.salt
(source: http://www.saltforum.org/saltforum/downloads/SALT1.0.pdf 2.6.1.2.2)

 

<?xml version="1.0"?>
<vxml version="2.0" xmlns="http://www.w3.org/2001/voice">
    <form>
        <field name="stock">
            <grammar src="./g_stock.grxml"/>
            <help> Please just say stock name. </help>
            Please say the stock name.
        </field>
        <field name="op">
            <grammar src="./g_op.grxml"/>
            <help> Please just say buy or sell. </help>
            Do you want to buy or sell?
        </field>
        <field name="quantity"> 
            <grammar src="./g_quant.grxml"/>
            <help> Please just say number of shares. </help>
            How many shares?
        </field>
        <field name="price">
            <grammar src="./g_price.grxml"/>
            <help> Please just say price. </help>
            What's the price?
        </field>
    </form>
</vxml>

Figure 4: stock.vxml

 

Entering a PIN

The next example show how to get a PIN number in both approaches.  The size disparity is less, because the hand-crafted SALT FIA needed for a single field is simple.

<html xmlns:salt="http://www.saltforum.org/02/SALT">
<body onload="sayWelcome.Start()">
    <form id="PIN" action="checkPIN.html">
        <input id="iptPIN" type="text" />
    </form>
    <salt:prompt id="sayWelcome" oncomplete="askPIN.Start(); recoPIN.Start()">
        Welcome to my speech recognition application. 
    </salt:prompt>
    <salt:prompt id="askPIN"> 
        Please say your password. 
    </salt:prompt>
    <salt:listen id="recoPIN" onreco="PIN.submit()">
        <salt:grammar src="PINdigits.grxml" />
        <salt:bind targetElement="iptPIN" />
    </salt:listen>
</body>
</html>
 
<?xml version="1.0"?>
<vxml version="2.0" xmlns="http://www.w3.org/2001/vxml">
    <form>
        <block>
            Welcome to my speech recognition application.
        </block>
        <field name="iptPIN">
            <grammar src="PINdigits.grxml"/>
            Please say your password.
        </field>
        <block>
            <submit next="checkPIN.vxml"/>
        </block>
    </form>
</vxml>
Figure 6: pin.vxml

 

Recording a Greeting

Here is an example of recording a greeting.

<html xmlns:salt="http://www.saltforum.org/2002/SALT">
    <!-- on page load, run script -->
    <body xmlns:salt="http://www.saltforum.org/2002/SALT" onload="RunAsk()">

        <form id="f1" action="http://www.example.com/savewaveform.aspx" method="get">
            <input name="vmail" type="hidden" />
        </form>

    <!-- Prompts -->
        <salt:prompt id="p_record" oncomplete="l_recordvm.Start()">
            Please speak after the tone. You may press any key to end your recording.
        </salt:prompt>
        <salt:prompt id="p_save">
            Do you want to save this voicemail?
        </salt:prompt>

    <!-- listens -->
    <!-- Recording session - max 60 seconds recording -->
        <salt:listen id="l_recordvm" initialtimeout="3000" 
                    endsilence="1500" babbletimeout="60000"
                    onreco="saveAudio()" onnoreco="saveAudio()" onsilence="RunAsk()" >
            <salt:record />
        </salt:listen>

    <!-- listen for capturing whether user wants to save voice mail -->
        <salt:listen id="l_save" onreco="processSave()">
            <salt:grammar src="./yesno.grxml" />
        </salt:listen>

        <salt:dtmf id="d_stop_rec" onreco="saveAudio()">
            <grammar src="alldigits.grxml" />
        </salt:dtmf>

    <!-- HTML script controlling dialog flow -->
        <script>
            function RunAsk() {
                if (voicemail.value=="") {
                    p_record.Start();
                }
            }

        // Ask user if they are satisfied with their recording
            function saveAudio () {
                p_save.Start();
                l_save.Start();
            }

        // If user is satisfied post file name back to web server
        // otherwise start again 
            function processSave () {
                smlResult = event.srcElement.recoresult;
                origNode = smlResult.selectSingleNode("//answer/text()");
                if (origNode.value == "Yes") {
                    vmail.value = l_recordvm.recordlocation;
                    f1.submit();
                } else {
                    RunAsk();
                }
            }
        </script>
    </body>
</html>
 
<?xml version="1.0"?>
<vxml version="2.0" xmlns="http://www.w3.org/2001/vxml">
    <form>
        <record name="greeting" beep="true" maxtime="60s"
                finalsilence="1500ms" dtmfterm="true" type="audio/wav">
            Please speak after the tone. You may press any key to end your recording.
        </record>
        <field name="save" type="boolean">
            Do you want to save this voice mail?
            <filled>
                <if cond="save">
                    <submit next="http://www.example.com/savewaveform.aspx" namelist="greeting" method="post"/>
                </if>
                <clear/>
            </filled>
        </field>
    </form>
</vxml>
Figure 8: record.vxml

Entering a From City and To City ("Unsafely")

The next two pairs are most instructive.  This pair shows how to gather a from city and a to city.  The SALT specification later claims that this example is "unsafe" (more on this below).  The VoiceXML example is "safe".

<html xmlns:salt="http://www.saltforum.org/2002/SALT"> 
  <body onload="RunAsk()"> 
    <form id="travelForm"> 
      <input name="txtBoxOriginCity" type="text" />
      <input name="txtBoxDestCity" type="text" />
    </form>

    <!-- Speech Application Language Tags --> 
    <salt:prompt id="askOriginCity"> Where would you like to leave from? </salt:prompt> 
    <salt:prompt id="askDestCity"> Where would you like to go to? </salt:prompt> 
    <salt:prompt id="sayDidntUnderstand" oncomplete="runAsk()">
      Sorry, I didn't understand.
    </salt:prompt>

    <salt:listen id="recoOriginCity" 
                  onreco="procOriginCity()" onnoreco="sayDidntUnderstand.Start()">
        <salt:grammar src="city.xml" /> 
    </salt:listen>

    <salt:listen id="recoDestCity" 
                  onreco="procDestCity()" onnoreco="sayDidntUnderstand.Start()"> 
        <salt:grammar src="city.xml" /> 
    </salt:listen>

    <!-- scripted dialog flow --> 
    <script> 
        function RunAsk() 
        { 
            if (travelForm.txtBoxOriginCity.value=="") { 
                askOriginCity.Start(); 
                recoOriginCity.Start(); 
            } else if (travelForm.txtBoxDestCity.value=="") { 
                askDestCity.Start(); 
                recoDestCity.Start(); 
            } 
        } 
        function procOriginCity() 
        { 
            travelForm.txtBoxOriginCity.value = recoOriginCity.text; 
            RunAsk(); 
        } 
        function procDestCity() 
        { 
            travelForm.txtBoxDestCity.value = recoDestCity.text; 
            travelForm.submit(); 
        } 
    </script>
  </body> 
</html>
Figure 9: fromto.salt
(source: http://www.saltforum.org/saltforum/downloads/SALT1.0.pdf 1.3)
 
<?xml version="1.0"?>
<vxml version="2.0" xmlns="http://www.w3.org/2001/voice">
    <form>
        <field name="txtBoxOriginCity">
            <grammar src="city.xml"/>
            Where would you like to leave from?
        </field>
        <field name="txtBoxDestCity">
            <grammar src="city.xml"/>
            Where would you like to go to?
        </field>
    </form>
</vxml>
Figure 10: fromto.vxml

 

Entering a From City and To City ("Safely")

This is the same example "made safe".

According to http://www.saltforum.org/saltforum/downloads/SALT1.0.pdf section 2.6.5 (A 'safe' voice-only dialog):

This example shows prompt and listen elements used with script in a simple voice-only dialog. Its point is to show that all possible user input and error events are caught and safely handled, so that the dialog is never left in a 'hanging' state.

So care needs to be taken to make the earlier SALT example work properly.  The VoiceXML is inherently "safe": VoiceXML interpreters must never leave a dialog in a "hanging state".

<html xmlns:salt="http://www.saltforum.org/2002/SALT">

<head>
    <title>origin and destination</title>
</head>

<body>
    <form id="travelForm" action="http://mysite.com/travel/inquire.php"
            method="post">
        <input name="txtBoxOriginCity" type="text" />
        <input name="txtBoxDestCity" type="text" />
    </form>

    <!-- SALT -->
    <salt:prompt id="askOriginCity" onerror="procError()">
        Where from?
    </salt:prompt>
    <salt:prompt id="askDestCity" onerror="procError()">
        Where to?
    </salt:prompt>
    <salt:prompt id="notUnderstood" onerror="procError()">
        Sorry, I could not understand your input.
    </salt:prompt>
    <salt:prompt id="operator"
        oncomplete="transferToOperator()"
        onerror="transferToOperator()">
        <!-- external function -->
        I am transferring you to an operator.
    </salt:prompt>

    <salt:listen id="recoOriginCity"
        onreco="procOriginCity()"
        onnoreco="procNothingUnderstood()"
        onsilence="procNothingUnderstood()"
        onerror="procError()">
        <salt:grammar src="./city.grxml" />
    </salt:listen>

    <salt:listen id="recoDestCity"
        onreco="procDestCity()"
        onnoreco="procNothingUnderstood()"
        onsilence="procNothingUnderstood()"
        onerror="procError()">
        <salt:grammar src="./city.grxml" />
    </salt:listen>

    <!-- scripts -->
    <script>
        function RunAsk()
        {
            if (txtboxOriginCity.value=="") {
                askOriginCity.Start();
                recoOriginCity.Start();
            } else if (txtboxDestCity.value=="") {
                askDestCity.Start();
                recoDestCity.Start();
            } else {
                <!-- all slots filled -->
                travelForm.submit();
            }
        }
        function procOriginCity ()
        {
            txtBoxOriginCity.value = recoOriginCity.value;
            RunAsk();
        }
        function procDestCity ()
        {
            txtBoxDestCity.value = recoDestCity.value;
            RunAsk();
        }
        function procNothingUnderstood()
        {
            notUnderstood.Start();
            RunAsk();
        }
        function procError()
        {
            operator.Start();
        }
        function terminate()
        {
            <!-- caller hung up -->
            window.close();
        }
    </script>

    <!-- on page load -->
    <script>
        <!-- detect disconnect at a central place instead of
            placing disconnect detect handlers in the listen objects -->
        callControl.attachEvent("call.disconnected ",terminate());
        <!-- start dialog execution -->
        RunAsk();
    </script>
</body>
</html>
Figure 11: safe.salt
(source: http://www.saltforum.org/saltforum/downloads/SALT1.0.pdf 2.6.5)
 
<?xml version="1.0"?>
<vxml version="2.0" xmlns="http://www.w3.org/2001/voice">
    <form>
        <nomatch> Sorry, I could not understand your input. </nomatch>
        <noinput> Sorry, I could not understand your input. </noinput>
        <error> 
            I am tranferring you to an operator.
            <goto next="transfer.vxml"/>
        </error>
        <field name="txtBoxOriginCity">
            <grammar src="city.xml"/>
            Where from?
        </field>
        <field name="txtBoxDestCity">
            <grammar src="city.xml"/>
            Where to?
        </field>
        <block>
            <submit next="http://mysite.com/travel/inquire.php" 
                    method="post" namelist="txtBoxOriginCity txtBoxDestCity"/>
        </block>
    </form>
</vxml>
Figure 12: safe.vxml

    About   |   News   |   Membership   |   Technology   |   Certification   |   Resources   |   FAQ  |  Sitemap   |   Contact

Copyright © 2000 - 2004 VoiceXML Forum. All rights reserved.
The VoiceXML Forum is a program of the
IEEE Industry Standards and Technology Organization (IEEE-ISTO)
For inquiries contact voicexml-admin@voicexml.org
This site is maintained by the VoiceXML Forum Webmaster