Tellme Studio

Home MyStudio About Tellme
VoiceXML Test API markup

The test API described in this document uses the complete schema specified in the VoiceXML 2.1 specification with the addition of a set of twelve elements in their own namespace (http://www.w3.org/2002/vxml-conformance) that greatly simplify the process of authoring tests and abstract the implementation details of the testing infrastructure. The elements are divided into four categories:

These elements are used to signal the completion of a test and, as such, SHOULD terminate test execution. They can appear anywhere that VXML executable.content is legal (e.g. block, event handlers, filled). Final status tags may be rendered in different ways. The most likely candidates are an exit with a return value, a submit, or a log followed by an exit.

pass
Indicates successful test completion. A transformation yielding a manually executed test could play the audio "pass" to the user running the test. A transformation yielding an automated test could play a sequence of DTMF tones indicating success to the test driver and submit a pass result to a reporting server. The element is allowed anywhere executable content is allowed in a VoiceXML document.
fail
Indicates unexpected results from the interpreter. A transformation yielding a manually executed test could play the audio "fail" to the user running the test. A transformation yielding an automated test could play a sequence of DTMF tones indicating failure to the test driver and submit a fail result to a reporting server. The element is allowed anywhere executable content is allowed in a VoiceXML document. The element supports the following optional attributes:
reason Optional. A simple text string explaining the probable cause for failure.
expr Optional. An ECMAScript expression that evaluates to a string at run-time providing information about the probable cause for failure.

These elements may be used to signal transitions in a multi-part test. They may appear anywhere that VXML executable.content is legal (e.g. block, event handlers, filled). Intermediate status tags may be rendered in different ways. The most likely candidates are using log or prompt or ignoring the element entirely.

comment
Specifies English language content that describes intermediate test results. The element is allowed anywhere executable content is allowed in a VoiceXML document and may contain plain text and zero or more value elements in any order. Note the following caveats with respect to the comment element:
  • Because the runtime impact is variable, this tag should NOT be used in situations where timing is being tested.
  • Because this tag may be ignored, a test author must take care that expressions specified in the context of the comment element have no runtime impact. For example, setting the expr attribute of the value element to "x = x + 1" within a comment not only displays the value of x but also increments its x. Leveraging such side-effects should be avoided.

These tags may be used at any point that input is required (e.g. initial, field, record, transfer) or on input-related event handlers (e.g. noinput and nomatch). These elements may be rendered in several different ways A few possibilities include playing DTMF prompts to control an external test driver, using properties to control the recognition result, or using platform-specific test features.

If these tags define prompts, they MUST provide separate prompts with counts 1 through 3.

speech
Sends a predefined utterance to a user or test driver. The response from the user or driver is expected to be an utterance matching a grammar. The speech element is allowed anywhere audio can be played in a VoiceXML document. Supports the following required attribute:
value Required. Uniquely identifies the utterance.
dtmf
Sends a request to a user or test driver to type or playback one or more DTMF digits. Supports the following required attribute:
value Required. The sequence of DTMF digits.
recording
Sends a request to a user or test driver to speak or playback audio to be recorded by the interpreter via execution of the record element. Supports the following required attribute:
value Required. A unique identifier that specifies the desired recording from the user or test driver. The possible values for the attribute include the following:
nonspeech The driver must recite a recording at least 5 seconds in length that does not contain one of the predefined utterance. An example is the popular nursery rhyme "Little Miss Muffett".
alpha, bravo, ... The driver must recite a recording containing the predefined utterance specified via the value attribute.

noinput
Requests that the test driver or caller play or say nothing in order to cause the interpreter to generate a noinput event. The optional duration attribute allows you to specify how many seconds the driver or caller should remain silent.
nomatch
Requests that the test driver or caller play or say something unrecognizable (out of grammar) in order to cause the interpreter to generate a nomatch event. The optional duration attribute allows you to specify how many seconds the driver or caller should provide the input.
hangup
Requests that the test driver or caller hang up. in order to cause the interpreter to generate a session.disconnect.hangup event.

The following attributes are supported by the speech, recording, dtmf, noinput, and nomatch elements.

count Optional. Specifies the value of the count attribute to specify on the generated <prompt> element. If the value is 0, a single <prompt> without a count attribute is generated. If the value is greater than 0, a single <prompt> is generated with its count attribute set to the value of the count attribute. If the count attribute is not specified, 3 <prompt> elements are generated each with its count attribute set to the value 1, 2, and 3 respectively.
pre_mark Optional. Specifies the name of the <mark> element to appear prior to the text contained in each generated <prompt> element.
post_mark Optional. Specifies the name of the <mark> element to appear after the text contained in each generated <prompt> element.

Grammars are expected to return one of three classes of results:

  • no semantic interpretation
  • a simple result
  • a structured result.

The utterance attribute specifies which audio input is expected to match this grammar. Grammars may map to a simple result by specifying an interpretation via the interp attribute. More complex results may be returned using the key element.

NOTE: A grammar element may NOT specify an interp attribute and one or more key elements simultaneously.

grammar
Specifies a grammar to be used when recognition is required by the test. Allowed anywhere a grammar element is allowed in a VoiceXML document. Supports the following attributes:
utterance Required. Specifies the unique identifier of an utterance.
interp Optional. Specifies a simple result string returned by the interpreter when the utterance is matched.
key
Supports the following attributes:
name Required. The string identifying the key. The string should be a valid ECMAScript variable name. Keys are used to express structured recognition results. Each key may contain either PCDATA or one or more key elements. Multiple keys with the same name may appear; this allows arrays to be built for complex results such as the 'pizza' example.
value Optional. A string representing the value the key. If the value is omitted, the key element element MUST contain one or more key elements.
phrase
Maps to a simple text string. The element is intended for phrase-based grammars such as VoiceXML choice and option elements. The element may also be used to construct SSML prompts. Supports the following required attribute:
utterance Specifies the unique identifier of an utterance.

The stylesheet author is required to select eight utterances, represented in the test framework by the first eight symbols in the International Radio Alphabet. In practice, the actual values will be specific to each language and may differ for each recognizer. These words or phrases should be carefully chosen such that speech utterances match corresponding grammars with high confidence scores. For example, setting the value attribute of the speech element to "alpha" should reliably match (i.e. produce a confidence of at least 0.5) a grammar that is rendered when setting the value of the utterance attribute of the grammar element to "alpha". Likewise, speech utterances should either produce low scores or not match grammars corresponding to different utterances. For example, setting the value attribute of the speech element to "alpha" should reliably return a confidence of less that 0.5 when match against the grammar produced by setting the utterance attribute of the grammar element to "bravo".

It should be reiterated that testing recognition accuracy is not a goal of this suite. Hence, the stylesheet author may freely select any eight phrases.

As defined in the Test API markup, the speech element should be used to request a predefined utterance from the user or test driver. In the document type definition (DTD) below, the 'ir-commands' entity defines the set of valid unique identifiers. The list is easily extended, and the XSLT should be updated to handled additional identifiers when processing the speech, grammar, and phrase elements.

The following DTD succintly declares the Test API markup elements, their attributes, and the legal values for those attributes if applicable.

<!ELEMENT conf:pass EMPTY>   
<!ELEMENT conf:fail EMPTY>
<!ATTLIST conf:fail
   reason CDATA #IMPLIED
   expr CDATA #IMPLIED>

<!ENTITY % ir-utterances 'alpha|bravo|charlie|delta|echo|foxtrot|golf|hotel'>
<!ENTITY % ir-commands '%ir-utterances;|help|cancel|exit|yes'>

<!ELEMENT conf:dtmf EMPTY>
<!ATTLIST conf:dtmf
   value CDATA #REQUIRED
   count CDATA #IMPLIED
   pre_mark CDATA #IMPLIED
   post_mark CDATA #IMPLIED>

<!ELEMENT conf:hangup   EMPTY >
<!ELEMENT conf:noinput   EMPTY >
<!ATTLIST conf:noinput
  duration CDATA #IMPLIED
   count CDATA #IMPLIED
   pre_mark CDATA #IMPLIED
   post_mark CDATA #IMPLIED>

<!ELEMENT conf:nomatch   EMPTY >
<!ATTLIST conf:nomatch 
  duration CDATA #IMPLIED
   count CDATA #IMPLIED
   pre_mark CDATA #IMPLIED
   post_mark CDATA #IMPLIED>

<!ELEMENT conf:recording   EMPTY >
<!ATTLIST conf:recording
   value (%ir-utterances;|nonspeech) #REQUIRED 
   count CDATA #IMPLIED
   pre_mark CDATA #IMPLIED
   post_mark CDATA #IMPLIED>

<!-- Add conf:speech to the menu element decl. -->
<!ELEMENT conf:speech EMPTY>
<!ATTLIST conf:speech
   value (%ir-commands;) #REQUIRED
   count CDATA #IMPLIED
   pre_mark CDATA #IMPLIED
   post_mark CDATA #IMPLIED>

<!ELEMENT conf:grammar (conf:key*)>   
<!ATTLIST conf:grammar 
  utterance (%ir-utterances;) #REQUIRED
  interp CDATA #IMPLIED
>

<!ELEMENT conf:key         (#PCDATA | conf:key)* >
<!ATTLIST conf:key
   name  CDATA  #REQUIRED 
   value  CDATA  #IMPLIED
>

<!ELEMENT conf:phrase      EMPTY >
<!ATTLIST conf:phrase
   utterance   (%ir-commands;) #REQUIRED >


<!ELEMENT conf:comment (#PCDATA | value)*>

<!ENTITY % ir-test-ext "conf:pass | conf:fail | conf:comment ">
<!ENTITY % ir-prompts "conf:speech | conf:dtmf | conf:hangup | 
  conf:noinput | conf:nomatch | conf:recording">


To incorporate the test API into the VoiceXML 2.1 DTD to validate test source against the DTD, perform the following steps:

  1. Add "xmlns:conf CDATA #IMPLIED" to the ATTLIST declaration of the vxml element.
  2. Add the test API ELEMENT and ENTITY declarations listed above to the DTD before the 'executable.content' ENTITY declaration.
  3. Add a reference to the 'ir-test-ext' ENTITY to the 'executable.content' ENTITY declaration.
  4. Add a reference to the 'ir-prompts' ENTITY to the following ELEMENT declarations: menu, field, initial, record, transfer, subdialog, and object.
  5. Add conf:phrase to the choice and option ELEMENT declarations.
  6. Add conf:grammar to the 'input' ENTITY declaration and to the link ELEMENT declaration.

Alternatively, you can transform your test source through the XSLT, and validate the output against the VoiceXML 2.1 DTD.

The following examples illustrate the use of the test API elements. The examples validate the XSLT used to generate valid VoiceXML from the test source. These tests should all pass before the XSLT is applied to the main body of tests.

The following example demonstrates simple usage of the conf:pass element. When the block is executed, the transformation of the conf:pass element will be executed.

<vxml version="2.1" xmlns="http://www.w3.org/2001/vxml"
   xmlns:conf="http://www.w3.org/2002/vxml-conformance">
  <form>
    <block>
      <conf:pass/>
    </block>
  </form>
</vxml>

The following example demonstrates simple usage of the conf:fail element. When the block is executed, the transformation of the conf:fail element will be executed.

<vxml version="2.1" xmlns="http://www.w3.org/2001/vxml"
   xmlns:conf="http://www.w3.org/2002/vxml-conformance">
  <form>
    <block>
      <conf:fail/>
    </block>
  </form>
</vxml>

The following example demonstrates usage of the reason attribute of the conf:fail element. When the block is executed, the transformation of the conf:fail element will be executed. Although some interpreters may ignore the reason attribute, others may output the value in a log element or submit it to a server-side script for further processing.

<vxml version="2.1" xmlns="http://www.w3.org/2001/vxml"
   xmlns:conf="http://www.w3.org/2002/vxml-conformance">
  <form>
    <block>
      <conf:fail reason="roulette"/>
    </block>
  </form>
</vxml>

The following example demonstrates usage of the reason attribute of the conf:fail element. When the block is executed, the transformation of the conf:fail element will be executed. Although some interpreters may ignore the expr attribute, others may output the value via a value element contained within a log element. In this example, the expr attribute will evaluate to "pete 3" at runtime.

<vxml version="2.1" xmlns="http://www.w3.org/2001/vxml"
   xmlns:conf="http://www.w3.org/2002/vxml-conformance">
  <form>
    <block>
      <conf:fail expr="'pete ' + (1 + 2)"/>
    </block>
  </form>
</vxml>

The following example demonstrates usage of the reason attribute of the conf:comment element. Although some interpreters may ignore the element, others may output the contents via a log element. Still others may output the contents via a prompt element. In this example, the interpreter should output "The value of x is 2" at runtime.

<vxml version="2.1" xmlns="http://www.w3.org/2001/vxml"
   xmlns:conf="http://www.w3.org/2002/vxml-conformance">
  <var name="x" expr="1+1"/>
  <form>
    <block>
      <conf:comment>
        The value of x is <value expr="x"/>. 
      </conf:comment>
      <conf:pass/>
    </block>
  </form>
</vxml>

The following example sends a request to the tester to hangup and catches the connection.disconnect.hangup event. If the event is caught, the interpreter executes the transformation of the conf:pass element. If some other event is executed or no event fires and the block is executed, the transformation of the conf:fail is executed.

<vxml version="2.1" xmlns="http://www.w3.org/2001/vxml"
   xmlns:conf="http://www.w3.org/2002/vxml-conformance">

  <catch><conf:fail expr="_event"/></catch>

  <form>
    <field name="one">
      <catch event="connection.disconnect.hangup">
        <conf:pass/>
      </catch>
      <catch><conf:fail expr="_event"/></catch>
      <conf:hangup/>
      <conf:grammar utterance="alpha"/>
    </field>

    <block><conf:fail reason="block"/></block>
  </form>
</vxml>

The following example sends a request for no input to the tester when field 'one' is executed. If the tester is silent and a noinput event is generated, the noinput handler should execute, and the interpreter should execute the noinput element. If some other event is executed or no event fires and the block is executed, the transformation of the conf:fail is executed.

<vxml version="2.1" xmlns="http://www.w3.org/2001/vxml"
   xmlns:conf="http://www.w3.org/2002/vxml-conformance">
  <catch><conf:fail reason="catch"/></catch>
  <form>
    <field name="one">
      <noinput><conf:pass/></noinput>
      <catch><conf:fail expr="_event"/></catch>
      <conf:noinput/>
      <conf:grammar utterance="alpha"/>
    </field>

    <block><conf:fail reason="block"/></block>
  </form>
</vxml>

The following example sends a request for a nomatch to the tester when field 'one' is executed. If the tester says or plays something out of grammar and a nomatch event is generated, the nomatch handler should execute, and the interpreter should execute the nomatch element. If some other event is executed or no event fires and the block is executed, the transformation of the conf:fail is executed.

<vxml version="2.1" xmlns="http://www.w3.org/2001/vxml"
   xmlns:conf="http://www.w3.org/2002/vxml-conformance">
  <catch><conf:fail expr="_event"/></catch>
  <form>
    <field name="one">
      <nomatch><conf:pass/></nomatch>
      <catch><conf:fail expr="_event"/></catch>
      <conf:nomatch/>
      <conf:grammar utterance="alpha"/>
    </field>

    <block><conf:fail reason="block"/></block>
  </form>
</vxml>

The following example demonstrate the usage of the conf:speech and conf:grammar elements. The conf:speech element is transformed into a series of prompts that correspond to the identifier "alpha". The conf:grammar element is transformed into a simple grammar that corresponds the phrase that matches the alpha utterance mapping. Since the interp attribute of the conf:grammar element is not specified the specific value returned by the interpreter when the grammar is matched cannot be tested. What can be tested is whether or not the form item variable one is defined. The block following the field peforms that check.

<vxml version="2.1" xmlns="http://www.w3.org/2001/vxml"
   xmlns:conf="http://www.w3.org/2002/vxml-conformance">

  <catch><conf:fail expr="_event"/></catch>

  <form>
    <block>
      <if cond="one != undefined">
        <conf:fail reason="initial check"/>
      </if>
    </block>

    <field name="one">
      <conf:speech value="alpha"/>
      <conf:grammar utterance="alpha"/>
    </field>

    <block>
      <if cond="one != undefined"><conf:pass/></if>
      <conf:fail reason="field assignment"/>
    </block>
  </form>

</vxml>

The following example demonstrates usage of the interp attribute of the conf:grammar element. If the tester utters the phrase that corresponds to "alpha", the interpreter recognizes the utterance and fills the form item variable one with the value "peña". When the block following the field is executed, the if element evaluates to true, and the transformation of the conf:pass element is executed.

<vxml version="2.1" xmlns="http://www.w3.org/2001/vxml"
   xmlns:conf="http://www.w3.org/2002/vxml-conformance">

  <catch><conf:fail reason="catch"/></catch>

  <form>
    <block>
      <if cond="one != undefined">
        <conf:fail reason="initial check"/>
      </if>
    </block>

    <field name="one">
      <conf:speech value="alpha"/>
      <conf:grammar utterance="alpha" interp="peña"/>
    </field>
    
    <block>
      <if cond="one=='peña'"><conf:pass/></if>
      <conf:fail reason="field assignment"/>
    </block>
  </form>
</vxml>

The following example demonstrates usage of the conf:key element to generate a structured result from a grammar. The conf:speech element instructs the tester to speak or play the utterance that corresponds to the identifier alpha. Upon recognition of this utterance, the interpreter should assign a reference to an object to the form item variable 'one'. The object should have properties x and y with the respective values 'valX' and 'valY'.

<vxml version="2.1" xmlns="http://www.w3.org/2001/vxml"
   xmlns:conf="http://www.w3.org/2002/vxml-conformance">

  <catch><conf:fail expr="_event"/></catch>

  <form>
    <block>
      <if cond="one != undefined">
        <conf:fail reason="initial check"/>
      </if>
    </block>

    <field name="one">
      <conf:speech value="alpha"/>
      <conf:grammar utterance="alpha">
        <conf:key name="x" value="valX"/>
        <conf:key name="y" value="valY"/>
      </conf:grammar>
    </field>

    <block>
      <if cond="typeof one == 'object' &amp;&amp; one.x == 'valX' &amp;&amp; one.y == 'valY'">
        <conf:pass/>
      </if>
      <conf:fail reason="field assignment"/>
    </block>
  </form>

</vxml>

The following example demonstrates more complex usage of the conf:key element to generate a structured result from a grammar. The conf:speech element instructs the tester to speak or play the utterance that corresponds to the identifier alpha. Upon recognition of this utterance, the interpreter should assign a reference to an object to the form item variable 'one'. The object should have properties x and y. x is a reference to an object and y is assigned the value 'valY'. The object referred to by x has properties a and b with respective values 'valA' and 'valB'.

<vxml version="2.1" xmlns="http://www.w3.org/2001/vxml"
   xmlns:conf="http://www.w3.org/2002/vxml-conformance">

  <catch><conf:fail expr="_event"/></catch>

  <form>
    <block>
      <if cond="one != undefined">
        <conf:fail reason="initial check"/>
      </if>
    </block>

    <field name="one">
      <conf:speech value="alpha"/>
      <conf:grammar utterance="alpha">
        <conf:key name="x">
          <conf:key name="a" value="valA"/>
          <conf:key name="b" value="valB"/>
        </conf:key>
        <conf:key name="y" value="valY"/>
      </conf:grammar>
    </field>

    <block>
      <if cond="typeof one != 'object'">
        <conf:fail reason="one is not an object"/>
      <elseif cond="one.y != 'valY'"/>
        <conf:fail reason="one.y had bad value"/>
      <elseif cond="typeof one.x != 'object'"/>
        <conf:fail reason="one.x is not an object"/>
      <elseif cond="typeof one.x.a != 'valA'"/>
        <conf:fail reason="one.x.a had bad value"/>
      <elseif cond="typeof one.x.b != 'valB'"/>
        <conf:fail reason="one.x.b had bad value"/>
      <else/>
        <conf:pass/>
      </if>
    </block>
  </form>
</vxml>

The following example demonstrates the use of the conf:phrase element to build a locale-independent menu.

<vxml version="2.1" xmlns="http://www.w3.org/2001/vxml"
   xmlns:conf="http://www.w3.org/2002/vxml-conformance">

  <catch event="menu-done"> <conf:pass/> </catch>
  <catch><conf:fail reason="catch"/></catch>

  <menu>
    <conf:speech value="alpha"/>
    <choice event="menu-done">
      <conf:phrase utterance="alpha"/>
    </choice>
  </menu>

</vxml>

The following example executes a mark, performs some recognition, and validates the mark shadow variables. The count attribute on the conf:speech element prevents the XSLT from generating a set of tapered prompts.

<vxml version="2.1" xmlns="http://www.w3.org/2001/vxml"
   xmlns:conf="http://www.w3.org/2002/vxml-conformance">
  <catch><conf:fail expr="'catch-all caught ' + _event"/></catch>
  <form>
    <field name="f1">
      <conf:speech value="alpha" pre_mark="mark1" count="0"/>
      <conf:noinput/>
      <conf:grammar utterance="alpha"/>
      <filled>
        <if cond="f1$.markname == 'mark1'">
          <if cond="f1$.marktime &gt; 0">
            <conf:pass/>
          <else/>
            <conf:fail expr="'unexpected mark time ' + f1$.marktime"/>
          </if>
        <else/>
            <conf:fail expr="'unexpected mark name ' + f1$.markname"/>
        </if>        
      </filled>
    </field>

    <block><conf:fail reason="block"/></block>
  </form>
</vxml>

The following is a listing of an XSLT that can be used to transform the previous example into valid VoiceXML 2.1 document. The "standalone" parameter allows you to define whether the test is to be run by a human or an automaton.

<?xml version="1.0"?> 
<!-- Copyright 1998-2003 W3C (MIT, ERCIM, Keio), All Rights Reserved. See http://www.w3.org/Consortium/Legal/. -->
<xsl:stylesheet
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:conf="http://www.w3.org/2002/vxml-conformance"
    xmlns="http://www.w3.org/2001/vxml"
    version="1.0">

<xsl:output cdata-section-elements="script"/>

<!-- ############################################# -->
<!-- D o c u m e n t   H e a d e r s               -->
<!-- ############################################# -->

<!-- Copy everything that doesn't match other rules -->
<xsl:template match="/ | @* | node()">
  <xsl:copy>
    <xsl:apply-templates select="@* | node()"/>
  </xsl:copy>
</xsl:template>

<!-- strip comments -->
<xsl:template match="comment()"/>

<!-- ############################################# -->
<!-- F i n a l   S t a t u s   I n d i c a t o r s -->
<!-- ############################################# -->

<!-- Success criteria -->
<xsl:template match="conf:pass">
  <prompt>pass</prompt>
  <exit/>
</xsl:template>

<!-- Failure criteria -->
<xsl:template match="conf:fail">
  <prompt>fail</prompt>
  <!-- the following only comes up in case of failure -->
  <xsl:if test="@reason != ''">
    <log>failure reason: <xsl:value-of select="@reason"/></log>
    <prompt><xsl:value-of select="@reason"/></prompt>
  </xsl:if>
  <xsl:if test="@expr != ''">
    <log>failure expression: <value expr="{@expr}"/></log>
    <prompt><value expr="{@expr}"/></prompt>
  </xsl:if>
  <exit/>
</xsl:template>

<!-- ############################################# -->
<!-- I n t e r m e d i a t e   R e p o r t s       -->
<!-- ############################################# -->

<!-- Copy everything doesn't match the other rules -->
<xsl:template match="conf:comment">
  <log>
    <xsl:apply-templates />
  </log>
</xsl:template>

<!-- ############################################# -->
<!-- I n p u t   I n d i c a t o r s               -->
<!-- ############################################# -->

<xsl:template match="conf:hangup">
  <prompt> Hang up now. </prompt>
</xsl:template>

<!-- Recite a recording that DOES contain the specified speech command (alpha, bravo, etc) -->
<xsl:template match="conf:recording[@value]">
  <prompt count="1"> 
      <xsl:if test="@pre_mark != ''">
      <mark name="{@pre_mark}"/>
      </xsl:if>
    Recite a sentence containing the word 
    '<xsl:call-template name="emit-name-from-token">
        <xsl:with-param name="token" select="@value"/>
      </xsl:call-template>'.
      <xsl:if test="@post_mark != ''">
      <mark name="{@post_mark}"/>
      </xsl:if>
  </prompt>
  <prompt count="2"> 
      <xsl:if test="@pre_mark != ''">
      <mark name="{@pre_mark}"/>
      </xsl:if>
    Recite a sentence containing the word 
    '<xsl:call-template name="emit-name-from-token">
        <xsl:with-param name="token" select="@value"/>
      </xsl:call-template>' again.
      <xsl:if test="@post_mark != ''">
      <mark name="{@post_mark}"/>
      </xsl:if>
  </prompt>
  <prompt count="3"> 
      <xsl:if test="@pre_mark != ''">
      <mark name="{@pre_mark}"/>
      </xsl:if>
    Recite a sentence containing the word 
    '<xsl:call-template name="emit-name-from-token">
        <xsl:with-param name="token" select="@value"/>
      </xsl:call-template>' one more time.
      <xsl:if test="@post_mark != ''">
      <mark name="{@post_mark}"/>
      </xsl:if>
  </prompt>
</xsl:template>

<xsl:template match="conf:recording[@value and @count='0']">
  <prompt> 
      <xsl:if test="@pre_mark != ''">
      <mark name="{@pre_mark}"/>
      </xsl:if>
    Recite a sentence containing the word 
    '<xsl:call-template name="emit-name-from-token">
        <xsl:with-param name="token" select="@value"/>
      </xsl:call-template>'.
      <xsl:if test="@post_mark != ''">
      <mark name="{@post_mark}"/>
      </xsl:if>
  </prompt>
</xsl:template>

<xsl:template match="conf:recording[@value and @count &gt; 0]">
  <prompt count="{@count}"> 
      <xsl:if test="@pre_mark != ''">
      <mark name="{@pre_mark}"/>
      </xsl:if>
    Recite a sentence containing the word 
    '<xsl:call-template name="emit-name-from-token">
        <xsl:with-param name="token" select="@value"/>
      </xsl:call-template>'.
      <xsl:if test="@post_mark != ''">
      <mark name="{@post_mark}"/>
      </xsl:if>
  </prompt>
</xsl:template>


<!-- Recite a recording at least 5 seconds in length that 
  does NOT contain a well-defined speech command (alpha, bravo, etc) -->
<!-- Little Miss Muffett sat on her tuffett, eating her curds and whey. 
  Along came a spider ... -->
<!-- Jack and Jill went up the hill to fetch a pail of water. 
  Jack fell down and broke his crown ... -->
<xsl:template match="conf:recording[@value='nonspeech']">
  <prompt count="1"> 
      <xsl:if test="@pre_mark != ''">
      <mark name="{@pre_mark}"/>
      </xsl:if>
    Recite your favorite nursery rhyme, for example, 'Little Miss Muffett'.
      <xsl:if test="@post_mark != ''">
      <mark name="{@post_mark}"/>
      </xsl:if>
  </prompt>
  <prompt count="2"> 
      <xsl:if test="@pre_mark != ''">
      <mark name="{@pre_mark}"/>
      </xsl:if>
    Recite your favorite nursery rhyme again.
      <xsl:if test="@post_mark != ''">
      <mark name="{@post_mark}"/>
      </xsl:if>
  </prompt>
  <prompt count="3"> 
      <xsl:if test="@pre_mark != ''">
      <mark name="{@pre_mark}"/>
      </xsl:if>
    Recite your favorite nursery rhyme one more time.
      <xsl:if test="@post_mark != ''">
      <mark name="{@post_mark}"/>
      </xsl:if>
  </prompt>
</xsl:template>

<xsl:template match="conf:recording[@value='nonspeech' and @count='0']">
  <prompt> 
      <xsl:if test="@pre_mark != ''">
      <mark name="{@pre_mark}"/>
      </xsl:if>
    Recite your favorite nursery rhyme, for example, 'Little Miss Muffett'.
      <xsl:if test="@post_mark != ''">
      <mark name="{@post_mark}"/>
      </xsl:if>
  </prompt>
</xsl:template>

<xsl:template match="conf:recording[@value='nonspeech' and @count &gt; 0]">
  <prompt count="{@count}"> 
      <xsl:if test="@pre_mark != ''">
      <mark name="{@pre_mark}"/>
      </xsl:if>
    Recite your favorite nursery rhyme, for example, 'Little Miss Muffett'.
      <xsl:if test="@post_mark != ''">
      <mark name="{@post_mark}"/>
      </xsl:if>
  </prompt>
</xsl:template>

<!-- ask the user to keep quiet -->
<xsl:template match="conf:noinput">
  <prompt count="1"> 
      <xsl:if test="@pre_mark != ''">
      <mark name="{@pre_mark}"/>
      </xsl:if>
    No input expected. Say nothing 
    <xsl:if test="@duration"> for <xsl:value-of select="@duration"/> seconds</xsl:if>.
      <xsl:if test="@post_mark != ''">
      <mark name="{@post_mark}"/>
      </xsl:if>
  </prompt>
  <prompt count="2"> 
      <xsl:if test="@pre_mark != ''">
      <mark name="{@pre_mark}"/>
      </xsl:if>
    No input expected. Say nothing again 
    <xsl:if test="@duration"> for <xsl:value-of select="@duration"/> seconds</xsl:if>.
      <xsl:if test="@post_mark != ''">
      <mark name="{@post_mark}"/>
      </xsl:if>
  </prompt>
  <prompt count="3"> 
      <xsl:if test="@pre_mark != ''">
      <mark name="{@pre_mark}"/>
      </xsl:if>
     No input expected. Say nothing one more time 
    <xsl:if test="@duration"> for <xsl:value-of select="@duration"/> seconds</xsl:if>.
      <xsl:if test="@post_mark != ''">
      <mark name="{@post_mark}"/>
      </xsl:if>
  </prompt>
</xsl:template>

<xsl:template match="conf:noinput[@count = 0]">
  <prompt> 
      <xsl:if test="@pre_mark != ''">
      <mark name="{@pre_mark}"/>
      </xsl:if>
    No input expected. Say nothing 
    <xsl:if test="@duration"> for <xsl:value-of select="@duration"/> seconds</xsl:if>.
      <xsl:if test="@post_mark != ''">
      <mark name="{@post_mark}"/>
      </xsl:if>
  </prompt>
</xsl:template>

<xsl:template match="conf:noinput[@count &gt; 0]">
  <prompt count="{@count}"> 
      <xsl:if test="@pre_mark != ''">
      <mark name="{@pre_mark}"/>
      </xsl:if>
    No input expected. Say nothing 
    <xsl:if test="@duration"> for <xsl:value-of select="@duration"/> seconds</xsl:if>.
      <xsl:if test="@post_mark != ''">
      <mark name="{@post_mark}"/>
      </xsl:if>
  </prompt>
</xsl:template>

<!-- ask the user to mumble something out of grammar -->
<xsl:template match="conf:nomatch">
  <prompt count="1"> 
      <xsl:if test="@pre_mark != ''">
      <mark name="{@pre_mark}"/>
      </xsl:if>
    Say something unrecognizable 
    <xsl:if test="@duration"> for <xsl:value-of select="@duration"/> seconds</xsl:if>.
      <xsl:if test="@post_mark != ''">
      <mark name="{@post_mark}"/>
      </xsl:if>
  </prompt>
  <prompt count="2"> 
      <xsl:if test="@pre_mark != ''">
      <mark name="{@pre_mark}"/>
      </xsl:if>
    Say something unrecognizable again 
    <xsl:if test="@duration"> for <xsl:value-of select="@duration"/> seconds</xsl:if>.
      <xsl:if test="@post_mark != ''">
      <mark name="{@post_mark}"/>
      </xsl:if>
  </prompt>
  <prompt count="3"> 
      <xsl:if test="@pre_mark != ''">
      <mark name="{@pre_mark}"/>
      </xsl:if>
    Say something unrecognizable one more time 
    <xsl:if test="@duration"> for <xsl:value-of select="@duration"/> seconds</xsl:if>.
      <xsl:if test="@post_mark != ''">
      <mark name="{@post_mark}"/>
      </xsl:if>
  </prompt>
</xsl:template>

<xsl:template match="conf:nomatch[@count = 0]">
  <prompt> 
      <xsl:if test="@pre_mark != ''">
      <mark name="{@pre_mark}"/>
      </xsl:if>
    Say something unrecognizable 
    <xsl:if test="@duration"> for <xsl:value-of select="@duration"/> seconds</xsl:if>.
      <xsl:if test="@post_mark != ''">
      <mark name="{@post_mark}"/>
      </xsl:if>
  </prompt>
</xsl:template>

<xsl:template match="conf:nomatch[@count &gt; 0]">
  <prompt count="{@count}"> 
      <xsl:if test="@pre_mark != ''">
      <mark name="{@pre_mark}"/>
      </xsl:if>
    Say something unrecognizable 
    <xsl:if test="@duration"> for <xsl:value-of select="@duration"/> seconds</xsl:if>.
      <xsl:if test="@post_mark != ''">
      <mark name="{@post_mark}"/>
      </xsl:if>
  </prompt>
</xsl:template>

<!-- special case a conf:speech inside a nomatch handler -->
<xsl:template match="*[name()='nomatch']/conf:speech[@value]" priority="2">
   <xsl:call-template name="emit-prompt">
     <xsl:with-param name="value"><xsl:value-of select="@value"/></xsl:with-param>
     <xsl:with-param name="pre_mark"><xsl:value-of select="@pre_mark"/></xsl:with-param>
     <xsl:with-param name="post_mark"><xsl:value-of select="@post_mark"/></xsl:with-param>
   </xsl:call-template>
</xsl:template>

<!-- special case a conf:speech inside a noinput handler -->
<xsl:template match="*[name()='noinput']/conf:speech[@value]" priority="2">
   <xsl:call-template name="emit-prompt">
     <xsl:with-param name="value"><xsl:value-of select="@value"/></xsl:with-param>
     <xsl:with-param name="pre_mark"><xsl:value-of select="@pre_mark"/></xsl:with-param>
     <xsl:with-param name="post_mark"><xsl:value-of select="@post_mark"/></xsl:with-param>
   </xsl:call-template>
</xsl:template>

<!-- special case a conf:speech inside a block -->
<xsl:template match="*[name()='block']/conf:speech[@value]" priority="2">
   <xsl:call-template name="emit-prompt">
     <xsl:with-param name="value"><xsl:value-of select="@value"/></xsl:with-param>
     <xsl:with-param name="pre_mark"><xsl:value-of select="@pre_mark"/></xsl:with-param>
     <xsl:with-param name="post_mark"><xsl:value-of select="@post_mark"/></xsl:with-param>
   </xsl:call-template>
</xsl:template>

<xsl:template match="conf:speech[@value]">
   <xsl:call-template name="emit-prompt">
     <xsl:with-param name="value"><xsl:value-of select="@value"/></xsl:with-param>
     <!-- explicit @count overrides tapering behavior -->
     <!-- to get a single prompt (no tapering) with no explicit count attribute, set @count="0" -->
     <xsl:with-param name="count" select="@count"/>
     <xsl:with-param name="taper">
       <xsl:choose>
         <xsl:when test="@count">0</xsl:when>
         <xsl:when test="@taper"><xsl:value-of select="@taper"/></xsl:when>
         <xsl:otherwise>1</xsl:otherwise>
       </xsl:choose>
     </xsl:with-param>
     <xsl:with-param name="pre_mark"><xsl:value-of select="@pre_mark"/></xsl:with-param>
     <xsl:with-param name="post_mark"><xsl:value-of select="@post_mark"/></xsl:with-param>
   </xsl:call-template>
</xsl:template>

<xsl:template match="*[name()='nomatch']/conf:dtmf[@value]" priority="2">
   <xsl:call-template name="emit-dtmf">
     <xsl:with-param name="value"><xsl:value-of select="@value"/></xsl:with-param>
     <xsl:with-param name="count" select="0"/>
     <xsl:with-param name="pre_mark" select="@pre_mark"/>
     <xsl:with-param name="post_mark" select="@post_mark"/>
   </xsl:call-template>
</xsl:template>

<xsl:template match="*[name()='noinput']/conf:dtmf[@value]" priority="2">
   <xsl:call-template name="emit-dtmf">
     <xsl:with-param name="value"><xsl:value-of select="@value"/></xsl:with-param>
     <xsl:with-param name="count" select="0"/>
     <xsl:with-param name="pre_mark" select="@pre_mark"/>
     <xsl:with-param name="post_mark" select="@post_mark"/>
   </xsl:call-template>
</xsl:template>

<xsl:template match="*[name()='block']/conf:dtmf[@value]" priority="2">
   <xsl:call-template name="emit-dtmf">
     <xsl:with-param name="value"><xsl:value-of select="@value"/></xsl:with-param>
     <xsl:with-param name="count" select="0"/>
     <xsl:with-param name="pre_mark" select="@pre_mark"/>
     <xsl:with-param name="post_mark" select="@post_mark"/>
   </xsl:call-template>
</xsl:template>

<xsl:template match="conf:dtmf[@value]">
   <xsl:call-template name="emit-dtmf">
     <xsl:with-param name="value"><xsl:value-of select="@value"/></xsl:with-param>
     <xsl:with-param name="count" select="@count"/>
     <xsl:with-param name="pre_mark" select="@pre_mark"/>
     <xsl:with-param name="post_mark" select="@post_mark"/>
   </xsl:call-template>
</xsl:template>

<!-- ############################################# -->
<!-- G r a m m a r s                               -->
<!-- ############################################# -->

<xsl:template match="conf:grammar[@interp and @utterance]" priority="2">
<xsl:variable name="rootname">CityName<xsl:value-of select="generate-id()"/></xsl:variable>
<grammar type="application/srgs+xml" root="{$rootname}" version="1.0">
  <rule id="{$rootname}" scope="public">
  <one-of>
     <item>
       <xsl:call-template name="emit-utterance">
         <xsl:with-param name="utterance"><xsl:value-of select="@utterance"/></xsl:with-param>
       </xsl:call-template>
      <tag>'<xsl:value-of select="@interp"/>'</tag>
    </item>
  </one-of>
  </rule>
</grammar>
</xsl:template>

<!-- an utterance without an explicit interpretation -->
<xsl:template match="conf:grammar[@utterance]" priority="1">
<xsl:variable name="rootname">CityName<xsl:value-of select="generate-id()"/></xsl:variable>
<grammar type="application/srgs+xml" root="{$rootname}" version="1.0">
  <rule id="{$rootname}" scope="public">
  <one-of>
    <item>
      <xsl:call-template name="emit-utterance">
         <xsl:with-param name="utterance"><xsl:value-of select="@utterance"/></xsl:with-param>
      </xsl:call-template>
    </item>
  </one-of>
  </rule>
</grammar>
</xsl:template>

<xsl:template match="conf:grammar[@utterance and descendant::conf:key]" priority="2">
<xsl:variable name="rootname">CityName<xsl:value-of select="generate-id()"/></xsl:variable>
<grammar type="application/srgs+xml" root="{$rootname}" version="1.0">
  <rule id="{$rootname}" scope="public">
  <one-of>
    <item>
      <xsl:call-template name="emit-utterance">
         <xsl:with-param name="utterance"><xsl:value-of select="@utterance"/></xsl:with-param>
      </xsl:call-template>

    <tag>
      <xsl:apply-templates select="conf:key"/>
    </tag>
    </item>
  </one-of>
  </rule>
</grammar>
</xsl:template>


<xsl:template match="conf:key[@value]" priority="2">
  <xsl:param name="path"/>
  <xsl:choose>  
  <xsl:when test="$path = ''">
    <xsl:text>var </xsl:text>
  </xsl:when>
  <xsl:when test="$path != ''">
    <xsl:value-of select="$path"/><xsl:text>.</xsl:text>
  </xsl:when>
 </xsl:choose>
  
  <xsl:value-of select="@name"/>
  <xsl:text>='</xsl:text>
  <xsl:value-of select="@value"/>
  <xsl:text>'; </xsl:text>
</xsl:template>

<xsl:template match="conf:key" priority="1">
  <xsl:param name="path"/>
 <xsl:choose>
  <xsl:when test="$path = ''">
    <xsl:text>var </xsl:text>
  </xsl:when>
  <xsl:when test="$path != ''">
    <xsl:value-of select="$path"/><xsl:text>.</xsl:text>
  </xsl:when>
</xsl:choose>
  <xsl:value-of select="@name"/><xsl:text>=new Object(); </xsl:text>
  <xsl:apply-templates select="conf:key">
    <xsl:with-param name="path">
      <xsl:if test="$path != ''">
        <xsl:value-of select="$path"/><xsl:text>.</xsl:text>
      </xsl:if>
      <xsl:value-of select="@name"/>
    </xsl:with-param>
  </xsl:apply-templates>
</xsl:template>


<xsl:template match="conf:phrase[@utterance]">
   <xsl:call-template name="emit-name-from-token">
     <xsl:with-param name="token" select="@utterance"/>
   </xsl:call-template>          
</xsl:template>

<!-- ############################################# -->
<!-- H e l p e r  T e m p l a t e s                            -->
<!-- ############################################# -->

<!-- for use in building grammars -->
<xsl:template name="emit-utterance">
<xsl:param name="utterance"/>
  <xsl:choose>
  <xsl:when test="$utterance='alpha'">chicago</xsl:when>
  <xsl:when test="$utterance='bravo'">san francisco</xsl:when>
  <xsl:when test="$utterance='charlie'">new york</xsl:when>
  <xsl:when test="$utterance='delta'">london</xsl:when>
  <xsl:when test="$utterance='echo'">tokyo</xsl:when>
  <xsl:when test="$utterance='foxtrot'">truth or consequences</xsl:when>
  <xsl:when test="$utterance='golf'">hackensack</xsl:when>
  <xsl:when test="$utterance='hotel'">standardsville</xsl:when>
  <xsl:when test="$utterance='help'">help</xsl:when>
  <xsl:when test="$utterance='cancel'">cancel</xsl:when>
  <xsl:when test="$utterance='exit'">exit</xsl:when>
  <xsl:when test="$utterance='yes'">yes</xsl:when>
  </xsl:choose>
</xsl:template>
<!-- Truth or Consequences is a real city in New Mexico, US.  Hackensack
     is located in New Jersey, US very close to the site of the Sept. 2001
     face-to-face.   And finally, yes, there really is a Standardsville.
     It's in Greene County, Virginia, US. -->

<!-- for use in building prompts -->
<xsl:template name="emit-name-from-token">
<xsl:param name="token"/>
  <xsl:choose>
    <xsl:when test="$token = 'alpha'">Chicago</xsl:when>
    <xsl:when test="$token = 'bravo'">San Francisco</xsl:when>
    <xsl:when test="$token = 'charlie'">New York</xsl:when>
    <xsl:when test="$token = 'delta'">London</xsl:when>
    <xsl:when test="$token = 'echo'">Tokyo</xsl:when>
    <xsl:when test="$token = 'foxtrot'">Truth or Consequences</xsl:when>
    <xsl:when test="$token = 'golf'">Hackensack</xsl:when>
    <xsl:when test="$token = 'hotel'">Standardsville</xsl:when>
    <xsl:when test="$token = 'help'">help</xsl:when>
    <xsl:when test="$token = 'cancel'">cancel</xsl:when>
    <xsl:when test="$token = 'exit'">exit</xsl:when>
    <xsl:when test="$token = 'yes'">yes</xsl:when>
  </xsl:choose>
</xsl:template>

<xsl:template name="emit-prompt">
  <xsl:param name="value"/>
  <xsl:param name="count" select="0"/>
  <xsl:param name="pre_mark"/>
  <xsl:param name="post_mark"/>
  
  <xsl:variable name="text_mapping">
    <xsl:call-template name="emit-name-from-token">
      <xsl:with-param name="token" select="$value"/>
    </xsl:call-template>          
  </xsl:variable>
  
  <xsl:choose>
  <xsl:when test="$count &gt;= 0">
    <prompt><xsl:if test="$count &gt; 0"><xsl:attribute name="count"><xsl:value-of select="$count"/></xsl:attribute></xsl:if>
            <xsl:if test="$pre_mark != ''">
            <mark name="{$pre_mark}"/>
            </xsl:if>
       Say '<xsl:value-of select="$text_mapping"/>'.
            <xsl:if test="$post_mark != ''">
            <mark name="{$post_mark}"/>
            </xsl:if>
    </prompt>
  </xsl:when>
  <xsl:otherwise> <!-- taper -->
    <prompt count="1">
            <xsl:if test="$pre_mark != ''">
            <mark name="{$pre_mark}"/>
            </xsl:if>
      Say '<xsl:value-of select="$text_mapping"/>'.
            <xsl:if test="$post_mark != ''">
            <mark name="{$post_mark}"/>
            </xsl:if>
    </prompt>
    <prompt count="2"> 
            <xsl:if test="$pre_mark != ''">
            <mark name="{$pre_mark}"/>
            </xsl:if>
      Say '<xsl:value-of select="$text_mapping"/>' again.      
            <xsl:if test="$post_mark != ''">
            <mark name="{$post_mark}"/>
            </xsl:if>
    </prompt>
    <prompt count="3">       
            <xsl:if test="$pre_mark != ''">
            <mark name="{$pre_mark}"/>
            </xsl:if>
      Say '<xsl:value-of select="$text_mapping"/>' one more time.
            <xsl:if test="$post_mark != ''">
            <mark name="{$post_mark}"/>
            </xsl:if>
    </prompt>
   </xsl:otherwise>
  </xsl:choose>     
</xsl:template>

<xsl:template name="emit-dtmf">
  <xsl:param name="value"/>
  <xsl:param name="count"/>
  <xsl:param name="pre_mark"/>
  <xsl:param name="post_mark"/>

  <xsl:choose>
    <xsl:when test="$count &gt;= 0">
      <prompt><xsl:if test="$count &gt; 0"><xsl:attribute name="count"><xsl:value-of select="$count"/></xsl:attribute></xsl:if>
      <xsl:if test="$pre_mark != ''">
      <mark name="{$pre_mark}"/>
      </xsl:if>
            Press '<xsl:value-of select="$value"/>'. 
    <xsl:if test="@duration"> for <xsl:value-of select="@duration"/> seconds</xsl:if>.
      <xsl:if test="$post_mark != ''">
      <mark name="{$post_mark}"/>
      </xsl:if>
      </prompt>
    </xsl:when>
  <xsl:otherwise>
    <prompt count="1"> 
            <xsl:if test="$pre_mark != ''">
            <mark name="{$pre_mark}"/>
            </xsl:if>
       Press '<xsl:value-of select="@value"/>'. 
            <xsl:if test="$post_mark != ''">
            <mark name="{$post_mark}"/>
            </xsl:if>
    </prompt>
    <prompt count="2"> 
            <xsl:if test="$pre_mark != ''">
            <mark name="{$pre_mark}"/>
            </xsl:if>
       Press '<xsl:value-of select="@value"/>' again. 
            <xsl:if test="$post_mark != ''">
            <mark name="{$post_mark}"/>
            </xsl:if>
    </prompt>
    <prompt count="3"> 
            <xsl:if test="$pre_mark != ''">
            <mark name="{$pre_mark}"/>
            </xsl:if>
       Press '<xsl:value-of select="@value"/>' one more time. 
            <xsl:if test="$post_mark != ''">
            <mark name="{$post_mark}"/>
            </xsl:if>
    </prompt>
  </xsl:otherwise>
  </xsl:choose>
</xsl:template>

</xsl:stylesheet>

The following is a listing of the output of Example 9 when transformed through the provided XSLT in "standalone" mode, that is, when a human is the test driver.

<vxml version="2.1" xmlns="http://www.w3.org/2001/vxml">
  <catch>
    <log>failure expression: 
    <value expr="_event" />
    </log>
    <audio>fail</audio>
    <exit />
  </catch>

  <form>
    <block>
      <if cond="one != undefined">
        <log>failure reason: initial check</log>
        <audio>fail</audio>
        <exit />
      </if>
    </block>

    <field name="one">
      <prompt count="1">Say 'Chicago'.</prompt>
      <prompt count="2">Say 'Chicago' again.</prompt>
      <prompt count="3">Say 'Chicago' one more time.</prompt>

      <grammar type="application/grammar+xml" root="CityName">
        <rule id="CityName" scope="public">
          <one-of>
            <item>Chicago</item>
          </one-of>
        </rule>
      </grammar>
    </field>

    <block>
      <if cond="one != undefined">
        <audio>pass</audio>
        <exit />
      </if>
      <log>failure reason: field assignment</log>
      <audio>fail</audio>
      <exit />
    </block>
  </form>
</vxml>

Tellme Networks, Inc.Terms of ServicePrivacy PolicyGeneral Disclaimers