Integrating RDC Tags with XHTML code
- Contributed by Shaivya Easwaren and Subramanian Narayanan
At present the RDC taglibs distribution provides support for generation of pure VXML form code. If there is a need to integrate RDC with X+V so that the resulting pages can be viewed in a multimodal browser like Opera, we need to carry out changes in two tag files within the taglibs-rdc.jar distribution:
- fsm-input.tag
- task.tag
The issues we face in the usage of RDC tags in JSM files (X+V JSP files) are as follows:
Opera 7.55, with which we carry out the testing, does not support external JavaScript file references
- VoiceXML parsing error is given on the auto-generated code for the following element:
<grammar xml:lang=”en-us” src="/SpringApp/.grammar/alpha.grxml" mode=”voice”/>
- There is no way by which we can call the VXML form from the XHTML form element through the use of an XML event since the forms getting generated have no ID associated with them
No <filled> and <assign> tags are getting generated - the utterance is not getting assigned to the correct form element, so the user has no way of knowing whether what he/she speaks is interpreted correctly by the VXML engine.
The VXML form tag getting generated has no namespace associated with it since it is getting generated under the default Voice XML namespace, i.e. wrapped in a <vxml> tag, which meant that no other DOCTYPE can be given for the document i.e. HTML incorporation in the page leads to a parsing error.
wedding photographers san francisco
To integrate “X” into an X+V JSP file, some changes were carried out in task.tag and fsm-input.tag. Changes carried out in task.tag:
- An additional form id attribute was added to the form element generated(an ID passed by the user in the rdc:task tag, that can be called on the occurrence of an XML event in relation with any XHTML element)
The VXML form was generated with the default VoiceXML namespace: http://www.w3.org/2001/vxml
<!--
<%@ taglib prefix="rdc" uri="http://jakarta.apache.org/taglibs/rdc-1.0" %>
<%@ attribute name="map" required="true" type="java.util.Map" %>
<%@ attribute name="id" required="true" type="java.lang.String" %>
---- /!\ '''Edit conflict - other version:''' ----
<%@ tag body-content="scriptless" %>[[http://hepburnspringsaccommodation.webs.com/hepburnsprings.htm |click for more]]
---- /!\ '''Edit conflict - your version:''' ----
<%@ tag body-content="scriptless" %>
---- /!\ '''End of edit conflict''' ----
-->
<rdc:comment>ToDo: figure out a way to gensym name map so we
can have more than one task per session</rdc:comment>
<jsp:useBean id="rdcStack" class="java.util.Stack" scope="request"/>
<rdc:push stack="${rdcStack}" element="${map}"/>
<form id="${id}" xmlns="http://www.w3.org/2001/vxml">
<jsp:doBody/>
</form>
<rdc:pop var="discard" stack="${rdcStack}"/>
Changes carried out in fsm-input.tag:
- The grammar inlining option was removed and only the grammar src was specified.
- The xv:id (where xv denotes the prefix for the XHTML+Voice namespace) was added while generating the field name to relate the default field name
(“<form-field-name>Input”) with the corresponding XHTML form field
A <filled> and nested <assign> tag was added to the fsm-input.tag file to assign the utterance value to the XHTML form field element.
<%--$Id: fsm-input.tag 218811 2005-06-25 15:42:36Z rubys $--%>
---- /!\ '''Edit conflict - other version:''' ----
<!--[[http://www.dananghotelsvietnam.com/ |http://www.dananghotelsvietnam.com]]
---- /!\ '''Edit conflict - your version:''' ----
<!--
---- /!\ '''End of edit conflict''' ----
<%@ taglib prefix="rdc" uri="http://jakarta.apache.org/taglibs/rdc-1.0"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="x" uri="http://java.sun.com/jsp/jstl/xml" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<%@ tag body-content="empty" %>
<%@ attribute name="model" required="true" type="java.lang.Object" %>
<%@ attribute name="state" type="java.lang.String" %>
-->
<c:set var="stateNode" value="${(empty state) ? 'input' : state}" />
<rdc:expand>
<rdc:get-configuration xml="${model.configuration}"
locator="/config/${stateNode}/events/link"/>
<rdc:get-configuration xml="${model.configuration}"
locator="/config/${stateNode}/events/catch"/>
</rdc:expand>
<field name="${model.id}Input" xv:id="${model.id}Input">
<rdc:expand>
<rdc:get-configuration xml="${model.configuration}"
locator="/config/${stateNode}/prompt-list/prompt"/>
</rdc:expand>
<c:forEach items="${model.grammars}" var="currentGrammar">
<grammar src="${currentGrammar.grammar}" />
</c:forEach>
<property name="maxnbest" value="${model.numNBest}"/>
<property name="confidencelevel" value="${model.minConfidence}"/>
<rdc:get-configuration xml="${model.configuration}"
locator="/config/${stateNode}/property-list/property"/>
<catch event= "repeat" >
<reprompt/>
</catch>
<c:if test="${model.className == 'org.apache.taglibs.rdc.SelectOne'}">
<c:if test="${model.optionsClass == 'org.w3c.dom.Document'}">
<rdc:get-configuration xml="${model.options}" locator="/list/option"/>
</c:if>
<c:if test="${model.optionsClass == 'org.apache.taglibs.rdc.SelectOne$Options'}">
${model.options}
</c:if>
</c:if>
<c:if test="${model.maxNoInput > 0}">
<noinput count="${model.maxNoInput}">
<var name="${model.id}ResultNBest" expr="'MAX_NOINPUT'"/>
<submit next="${model.submit}" method="post" namelist="${model.id}ResultNBest"/>
</noinput>
</c:if>
<rdc:get-configuration xml="${model.configuration}"
locator="/config/${stateNode}/noinput-list/noinput"/>
<c:if test="${model.maxNoMatch > 0}">
<nomatch count="${model.maxNoMatch}">
<var name="${model.id}ResultNBest" expr="'MAX_NOMATCH'"/>
<submit next="${model.submit}" method="post" namelist="${model.id}ResultNBest"/>
</nomatch>
</c:if>
<rdc:get-configuration xml="${model.configuration}"
locator="/config/${stateNode}/nomatch-list/nomatch"/>
<rdc:get-configuration xml="${model.configuration}"
locator="/config/${stateNode}/help-list/help"/>
<filled>
<assign name="document.forms[0].${model.id}.value" expr="${model.id}Input" />
</filled>
</field>Now the taglibs-rdc.jar file is ready to be integrated in the Struts-based X+V application. An X+V JSP file can be written using RDC taglibs to accept voice input as follows:
<!DOCTYPE html PUBLIC "-//VoiceXML Forum//DTD XHTML+Voice 1.2//EN" "http://www.voicexml.org/specs/multimodal/x+v/12/dtd/xhtml+voice12.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ev="http://www.w3.org/2001/xml-events" xmlns:xv="http://www.voicexml.org/2002/xhtml+voice" xml:lang="en-US">
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<%@ taglib uri="http://jakarta.apache.org/taglibs/rdc-1.0" prefix="rdc"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<head>
<title>Example 1: Using RDC and Struts</title>
<xv:sync xv:input="userid" xv:field="useridInput"/>
<form xmlns="http://www.w3.org/2001/vxml" id="sayHello">
<rdc:hello name="shaivya"/>
</form>
<jsp:useBean id="dialogMap" class="java.util.LinkedHashMap" scope="session"/>
<rdc:task map="${dialogMap}" id="takeText">
<rdc:digits id="userid" minLength="5" maxLength="6" echo="true" />
<rdc:alphanum id="username" minLength="10" maxLength="10" pattern="[0-9]*" confirm="true" echo="true"/>
<rdc:date id="birthdate" minDate="01011981" maxDate="12312005" echo="true"/>
</rdc:task>
</head>
<body ev:event="load" ev:handler="#takeText">
<h1>First RDC Example</h1>
<center>
<html:form action="/DummyAction">
User ID: <html:text property="userid" size="20"/><br/><br/>
Username: <html:text property="username" size="20"/><br/><br/>
Date of Birth: <html:text property="birthdate" size="20"/><br/><br/>
<html:submit value="Submit"/>
</html:form>
</body>
</html>The source code that gets generated is as follows:
<!DOCTYPE html PUBLIC "-//VoiceXML Forum//DTD XHTML+Voice 1.2//EN" "http://www.voicexml.org/specs/multimodal/x+v/12/dtd/xhtml+voice12.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ev="http://www.w3.org/2001/xml-events" xmlns:xv="http://www.voicexml.org/2002/xhtml+voice" xml:lang="en-US">
<head>
<title>Example 1: Using RDC and Struts</title>
<xv:sync xv:input="userid" xv:field="useridInput"/>
<form xmlns="http://www.w3.org/2001/vxml" id="sayHello">
<block><prompt>Hello World from shaivya</prompt></block>
</form>
<form id="takeText" xmlns="http://www.w3.org/2001/vxml">
<field name="useridInput" xv:id="useridInput">
<prompt>
Please specify the digits.
</prompt>
<grammar src="/SpringApp/.grammar/digits.grxml" />
<grammar src="/SpringApp/.grammar/digits-dtmf.grxml" />
<property name="maxnbest" value="1"/>
<property name="confidencelevel" value="0.4"/>
<property name="incompletetimeout" value="1s"/><property name="completetimeout" value="1s"/>
<catch event= "repeat" >
<reprompt/>
</catch>
<noinput count="1">
<prompt>I did not hear you speak the digits.</prompt>
</noinput><noinput count="2">
<prompt>Could you please repeat the digits?</prompt>
</noinput><noinput count="3">
<prompt>I appear to be having trouble hearing you.
Waiting for you to speak the digits. </prompt>
</noinput>
<nomatch>
<prompt>I am sorry. I didn't understand you. Please repeat the
digits.</prompt>
</nomatch>
<help>
<prompt>You need to specify a value like 1 2 3 4.</prompt>
</help>
<filled>
<assign name="document.forms[0].userid.value" expr="useridInput" />
</filled>
</field>
<field name="usernameInput" xv:id="usernameInput">
<prompt>Please specify an alphanumeric value.</prompt>
<grammar src="/SpringApp/.grammar/alphanum.grxml" />
<property name="maxnbest" value="1"/>
<property name="confidencelevel" value="0.4"/>
<property name="incompletetimeout" value="1s"/><property name="completetimeout" value="1s"/>
<catch event= "repeat" >
<reprompt/>
</catch>
<noinput count="1">
<prompt>I did not hear you speak the alphanumeric value.</prompt>
</noinput><noinput count="2">
<prompt>Could you please repeat the value?</prompt>
</noinput><noinput count="3">
<prompt>I appear to be having trouble hearing you.
Waiting for you to speak the value. </prompt>
</noinput>
<nomatch>
<prompt>I am sorry. I didn't understand you. Please repeat the
input.</prompt>
</nomatch>
<help>
<prompt>You need to specify an alphanumeric value like L W 1 4 8.</prompt>
</help>
<filled>
<assign name="document.forms[0].username.value" expr="usernameInput" />
</filled>
</field>
<field name="birthdateInput" xv:id="birthdateInput">
<prompt>Please specify a date.</prompt>
<grammar src="/SpringApp/.grammar/date.grxml" />
<property name="maxnbest" value="1"/>
<property name="confidencelevel" value="0.4"/>
<property name="incompletetimeout" value="1s"/><property name="completetimeout" value="1s"/>
<catch event= "repeat" >
<reprompt/>
</catch>
<noinput>
<prompt>I did not hear you speak a date.</prompt>
</noinput><noinput>
<prompt>Could you please repeat the date?</prompt>
</noinput><noinput>
<prompt>I appear to be having trouble hearing you.
Waiting for you to say a date.</prompt>
</noinput>
<nomatch>
<prompt>I'm sorry, I was expecting a date.</prompt>
</nomatch><nomatch>
<prompt>Could you repeat that please?</prompt>
</nomatch>
<help>
<prompt>Please specify a complete date.</prompt>
</help><help>
<prompt>For instance, say January first, 2004.</prompt>
</help><help>
<prompt>You can also use alternate forms like first of April.</prompt>
</help>
<filled>
<assign name="document.forms[0].birthdate.value" expr="birthdateInput" />
</filled>
</field>
</form>
</head>
<body ev:event="load" ev:handler="#takeText">
<h1>First RDC Example</h1>
<center>
<form name="userIdBean" method="post" action="/SpringApp/DummyAction.do;jsessionid=DC4FF33378A5D261F8C040729AFC2EF9">
User ID: <input type="text" name="userid" size="20" value=""><br/><br/>
Username: <input type="text" name="username" size="20" value=""><br/><br/>
Date of Birth: <input type="text" name="birthdate" size="20" value=""><br/><br/>
<input type="submit" value="Submit">
</form>
</body>
</html>This source code is the same that would be written for an X+V JSP file with VXML forms coded from scratch.
- The VXML form is generated with the default namespace so the VXML wrapper element is no longer there (so no parsing errors)
- It calls the appropriate VXML form on the occurrence of an XML event in an XHTML element
- It relates the XHTML form fields with VXML fields through the xv:sync element, and assigns the utterance value to the appropriate field.
- It allows integration of Struts HTML tags, as well as html tags through the usage of appropriate namespaces
The above page can be deployed on a web server like Tomcat and tested in a multimodal browser like Opera for a visual + voice experience.