data

data element

Provides programmatic access to data in XML format from an HTTP server without transitioning to a new VoiceXML document.

Subsection Heading

Insert subsection body here.

Syntax

<data 
enctype = "encoding_type"
fetchaudio = "URI"
fetchaudioexpr = "ECMAScript_Expression"
fetchhint = "string"
fetchtimeout = "string"
maxage = "seconds"
maxstale = "seconds"
method = "string"
name = "ECMAScript_variable"
namelist = "string"
src = "URI"
srcexpr = "ECMAScript_Expression"
/>

Attributes

enctype

The MIME encoding type of the submitted data. To specify the following encodings, you must set the value of the method attribute to "POST", and you must use the namelist attribute to specify the variables to be submitted.

application/x-www-form-urlencodedThe data is submitted using the encoding described in Section 2.2 of RFC 1738. This results in name/value pairs sent to the server as name1=value1&name2=value2... with space characters replaced by "+" and reserved characters (like "#") replaced by "%HH" where HH is the ASCII code of the character in hexadecimal. Line breaks are encoded as "%0D%0A" - a carriage return followed by a line feed.
multipart/form-dataThe data is submitted using the encoding described in RFC 2388. The encoding provides an efficient means for sending large quantities of binary data or text containing non-ASCII characters. When submitting a variable that references recorded audio, the enctype is automatically set to "multipart/form-data".

expr

DEPRECATED. Use srcexpr instead.

fetchaudio

The URI of the audio clip to play while the interpreter fetches the resource. For complete details on the proper use of this attribute, read the fetchaudio tutorial.

fetchaudioexpr

An ECMAScript expression that evaluates to the URI used for fetchaudio. This attribute is a Tellme extension.

fetchhint

Defines when the interpreter context may retrieve documents from the server.

prefetchDocuments may be prefetched.
safeDocuments may only be fetched when needed, never before.

fetchtimeout

The time in seconds (s) or milliseconds (ms) for the VoiceXML interpreter to wait for content to be returned by the HTTP server before throwing an error.badfetch event. The fetchtimeout value is rounded down to the nearest whole second (e.g., 5700ms or 5.7s would be rounded down to 5s). If fetchtimeout has a value less than 1 second, it is reset to the default value. The default value is 15s.

maxage

Sends the max-age Cache-Control HTTP header along with the request for the specified resource. The header indicates that the document is willing to use content whose age is no greater than the specified time in seconds, unless maxstale is also provided. Voice application developers should use extreme caution when setting this attribute. If used improperly, it could have an adverse affect on the performance of your application. You should only consider using this attribute in requests for frequently changing content (e.g. dynamically generated content) hosted on a misconfigured HTTP server that you do not control. To reduce load, some HTTP servers are configured to indicate to clients that content expires some arbitrary time in the future. In that case, set the maxage attribute to 0. If you do control the HTTP server, you should instead configure the HTTP server to omit the expires header and possibly to send the Cache-Control: no-cache header. The former requires the VoiceXML interpreter to check with the server before using any cached content. The latter requires the VoiceXML interpreter to not cache the fetched resource.

maxstale

Instructs the VoiceXML interpreter to send a max-stale Cache-Control header along with the HTTP request for the specified resource. The header indicates that the document is willing to use content that has exceeded its expiration time by no more than the specified number of seconds. Voice application developers should use extreme caution when setting this attribute. If used improperly, your application may present stale content to users. If you do control the HTTP server, you should instead configure the HTTP server to send an expires header with a time in the distant future.

method

The HTTP method used to send the request.

GETThe request is submitted using the GET method.
POSTThe request is submitted using the POST method.

name

The name of a variable that exposes the data to script.

namelist

A space-separated list of variables to be submitted via HTTP to the specified document.

src

The URI of the data.

srcexpr

An ECMAScript expression that evaluates to the URI of the data. Use this attribute to dynamically modify the URI sent to the document server that returns the data.

Parents

block, catch, error, filled, foreach, form, help, if, menu, noinput, nomatch, prompt, vxml

Children

None.

Remarks

The data element allows the developer to include arbitrary data in a voice application and to reference that data via script. The data consumed by the data element must be formatted in XML, and the Tellme VoiceXML interpreter exposes that data via a subset of the W3C Document Object Model (DOM).

The VoiceXML interpreter evaluates the data element when the element is encountered during the flow of VoiceXML execution. If, for example, the data element is a child of the vxml element, then the data exists in document scope and is only loaded when the page loads. If, for example, the data element is a child of a block, the data exists in the anonymous scope of the block and is loaded whenever the block is executed in linear order of the executable elements in the block.

If an HTTP error occurs while fetching the data or the data returned is not well-formed XML, the VoiceXML interpreter throws error.badfetch.

To access data across domains, subdialog to a VoiceXML document in the domain where the data resides. The subdialog specifies a data element and returns the named variable in the namelist of the return element in the subdialog.

The src and the srcexpr attributes are mutually exclusive.

The root document element of the XML data retrieved by the data element cannot be named "vxml". If the data element fetches a document containing a root document element named "vxml", the VoiceXML interpreter throws the event error.badfetch, and the variable associated with the name attribute of the data element is set to null.

If any of the fetchtimeout, fetchhint, maxage, or maxstale attributes is not specified for a data element, then the value of the fetchtimeout, documentfetchhint, documentmaxage, or documentmaxstale property, respectively, is used.

The fetchaudio and fetchaudioexpr attributes are mutually exclusive. If both of these attributes are specified an error.badfetch event is thrown.

Prior to Revision 3, the interpreter ignores any undeclared variables in the namelist attribute. In Revision 3 and later, the interpreter throws error.semantic if any of the variables is undeclared.

Examples

The example that follows assumes that the data retrieved by the data element is returned in a specific XML format (schema). A sample instance of that schema follows:

<?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 following example uses the data element to load a list of subjects and to play that list to the user. The GetSubjects function uses the DOM to access the id and name of each subject node. The data is returned as an array of objects. Each object contains a tts and a wav property which are consumed by the audio element.

<?xml version="1.0"?>
<vxml version="2.1"
 xmlns="http://www.w3.org/2001/vxml">

   <catch event="error.badfetch">
<!-- 
In this example, the data tag is the only resource that could 
have caused this error. In a real application, however, failure 
to fetch other resources such as scripts and grammars may 
have caused the fetch error, so either bail out as demonstrated here 
or check the named variable for null before accessing it. 
In a catastrophic situation like this, consider transferring the customer 
to a live agent.
-->
      <log>An HTTP fetch error occurred. Terminating...</log>
      <exit />
   </catch>
   
   <data src="subjects.exml" name="oSubjects" />

   <script>
   <![CDATA[
   // accept a DOM reference and return an array of (tts, wav) tuples
   function GetSubjects(oData)
   {
      var aSubjects = [];

      // use exception handling (SEH) in case the xml you got back
      // isn't what you expected
      try {
         var oRoot = oData.documentElement;
         for (var i = 0; i < oRoot.childNodes.length; i++)
         {
            var child = oRoot.childNodes.item(i);
            if (child.nodeType == Node.ELEMENT_NODE &&
                child.nodeName == 'subject') {
              var sID = child.getAttribute("id");
              var oName = GetFirstChildByName(child, "name");
              var sName = (oName ? oName.firstChild.data : "");
              aSubjects.push({'tts' : sName, 'wav' : sID + '.wav'});
            }
         }
      }
      catch(e)
      {
         Log("GetSubjects exception: " + e);
      }

      return aSubjects;
   }

   // perform a shallow traversal of oNode, and return the first child 
   // node encountered with the specified node name
   function GetFirstChildByName(oNode, sName)
   {
      for (var iChild = 0; iChild < oNode.childNodes.length; iChild++)
      {
         var oChild = oNode.childNodes.item(iChild);
         if (oChild.nodeName == sName)
         {
            return oChild;
         }
      }

      return null;
   }

   function Log(s) { vxmllog(s); }
   ]]>
   </script>
   <form>
      <!-- retrieve a list of subjects -->
      <var name="aSubjects" expr="GetSubjects(oSubjects)"/>
      <block>
         <log>Subject count=<value expr="aSubjects.length"/></log>
         <if cond="aSubjects.length &gt; 0">
            Here's the list of subjects
            <!-- since we have subjects, play them back to the user -->
            <foreach item="oSubject" array="aSubjects">
               <audio expr="oSubject.wav">
                  <value expr="oSubject.tts"/>
               </audio>
               <break size="small"/>
            </foreach>
         <else/>
            There are no subjects.
         </if>
      </block>
   </form>
</vxml>

The example that follows assumes that the data retrieved by the data element is returned in a specific XML format (schema). A sample instance of that schema follows:

<?xml version="1.0"?>
<?access-control allow="*"?>
<quote>
   <name>Ford Motor Company</name>
   <ticker>F</ticker>
   <open>28.35</open>
   <last>28.72</last>
   <change>.54</change>
   <day_high>29.03</day_high>
   <day_low>28.03</day_low>
</quote>

The following example requests a company name from the user and calls a subdialog that retrieves and reads back the associated stock data for that company.

<?xml version="1.0"?>
<vxml version="2.1"
 xmlns="http://www.w3.org/2001/vxml">

<error>
   We are experiencing technical difficulties. Try back later.
   <exit />
</error>

<!-- establish some variables to protect us from changing server URIs -->
<!-- these are fictitious. replace them with real URIs -->
<var name="url_base" expr="'http://www.quotesrus.com/stocks/'"/>
<var name="url_audio" expr="url_base + 'audio/'"/>
<var name="url_qsvr" expr="url_base + 'quotes.cgi'"/>

<var name="ticker"/> <!-- share ticker symbol between dialogs -->

<!-- 
   retrieve the name of a company from the user 
   the fictitious grammar returns the company name as a ticker symbol
-->
<form id="get_coname">
   <field name="ticker">
      <prompt>Say a company name</prompt>
      <!-- 
      the following is a url to a fictitious grammar containing
      company names
      -->
      <grammar type="application/srgs+xml" mode="voice"
         src="http://www.quotesrus.com/stocks/grammars/conames.gsl"/>
      <catch event="nomatch noinput">
         Sorry. I didn't get that. 
         Say a company name or enter a ticker symbol.
      </catch>
      <filled>
         <!-- 
            assign ticker symbol to var at document scope 
            for use in read_quote
         -->
         <assign name="document.ticker" expr="ticker"/>
         <goto next="#read_quote_proxy"/>
      </filled>
   </field>
</form>

<!-- 
   The following dialog is a proxy dialog that executes a subdialog 
   to a quote reader. 
   Pass the ticker, base audio url, and quote server url 
   to the subdialog as parameters.
-->
<form id="read_quote_proxy">
   <subdialog src="quotereader.vxml" name="oResult">
      <param name="ticker" expr="document.ticker"/>
      <param name="url_audio" expr="document.url_audio"/>
      <param name="url_qsvr" expr="document.url_qsvr"/>
      <filled>
         <if cond="oResult.success">
            <!-- get the next company name -->
            <goto next="#get_coname"/>
         <else/>
            <!-- error reading quote; bail! -->
            <throw event="error.fatal"/>
         </if>
      </filled>
   </subdialog>
</form>

</vxml>

The following example implements a subdialog that reads back to the user a stock quote for a company specified by its ticker symbol. The data element is re-executed each time the subdialog is called, resulting in a new query sent to the Web server that returns the data.

<?xml version="1.0"?>
<vxml version="2.1"
 xmlns="http://www.w3.org/2001/vxml">
<!--
This dialog accepts a ticker symbol, a url to audio, 
and a url to a quote server. It retrieves XML data from the quote server 
using the data tag, plays back the quote data, and returns a status code. 
The caller can check the status code as a property of the 
object variable associated with the name attribute of the subdialog element.
-->
   <form id="play_quote">
      <var name="ticker"/> <!-- ticker param -->
      <var name="url_audio"/> <!-- audio base url param -->
      <var name="url_qsvr"/> <!-- quote server param -->

      <catch event="error.badfetch"> <!-- handle data fetch error -->
        <log>unable to fetch quote data: 
            <value expr="urlquotes + qstring"/></log>
        <assign name="success" expr="false"/>
        <return namelist="success"/>
      </catch>

      <script><![CDATA[
      // Convert the shallow DOM tree (oData) to a JavaScript object (obj)
      // Property names of obj correspond to DOM node names.
      function DOM2JS(oData)
      {
         var obj = {};
      
         try {
            var oRoot = oData.documentElement;
            for (var iChild = 0; iChild < oRoot.childNodes.length; iChild++)
            {
               var oChild = oRoot.childNodes.item(iChild);
               if (oChild.nodeType == Node.ELEMENT_NODE) {
                 obj[oChild.nodeName] = oChild.firstChild.data;
               }
            }
         }
         catch(e)
         {
            Log("DOM2JS exception : " + e);
         }
      
         return obj;
      }

      // return the value of the property sName,
      // or return vDefault if the property doesn't exist
      function GetData(oJSData, sName, vDefault)
      {
         return (null != oJSData[sName] ? oJSData[sName] : vDefault);
      }

      function Log(s) { vxmllog(s); }
      ]]></script>

      <!-- status to return to caller -->
      <var name="success" expr="true"/>

      <block>
         <!-- compose the query string -->
         <var name="qstring" expr="'?ticker=' + ticker"/> 
         <!-- fetch the data -->
         <data srcexpr="url_qsvr + qstring" name="oQuoteData"/> 
         <var name="oJSQuote" expr="DOM2JS(oQuoteData)"/>

         <!-- retrieve the change in the stock's value -->
         <var name="change" expr="GetData(oJSQuote, 'change', 0)"/>

         <!--play the company name -->
         <audio expr="url_audio + ticker + '.wav'">
            <value expr="GetData(oJSQuote, 'name', 'unknown')"/>
          </audio>
         <!-- play 'unchanged, 'up', or 'down' based on zero, 
            positive, or negative change -->
         <if cond="change == 0">
            <audio src="url_audio + unchanged_at.wav"/>
         <else/>
            <if cond="change &gt; 0">
               <audio src="url_audio + up.wav"/>
            <else/> <!-- negative -->
               <audio src="url_audio + down.wav"/>
            </if>
            <audio src="url_audio + to.wav"/>
            <!-- play change in value as positive number -->
            <value expr="Math.abs(change)"/>
         </if>
         <!-- play the current price per share -->
         <value expr="GetData(oJSQuote, 'last', 0)"/>
         <break size="medium"/>
         <return namelist="success"/>
      </block>
   </form>
</vxml>

See Also

Tellme Document Object Model reference, Tutorial: Using the data element, W3C Document Object Model (DOM) Level 2 Core Specification