|
In this monthly column, an industry expert will answer common questions about VoiceXML and related technologies. Readers are encouraged to submit questions about VoiceXML, including development, voice-user interface design, and speech technology in general, or how VoiceXML is being used commercially in the marketplace. If you have a question about VoiceXML, e-mail it to and be sure to read future issues of VoiceXML Review for the answer.
By Matt Oshry
Q: AJAX has rapidly changed how developers look at web UIs. Are any of the AJAX advantages possible in VoiceXML?
A: Yes! AJAX is incredibly powerful because it allows you to build seamless user interfaces that dynamically pull in XML data. This development paradigmn is great for VoiceXML because you really want to make your VoiceXML and Javascript super-fast to load and only fetch that dynamic data when you need it. (For those not familiar with AJAX, check out Ajax: A New Approach to Web Applications.) Instead of XMLHttpRequest, VoiceXML 2.1 makes this functionality a first-class citizen through the element. Now, the isn't really asynchronous, but that doesn't really restrict you from using it to dynamically pull in that XML data. Let's walk through an example that uses AJAX to list your RSS feed in your web page and your VoiceXML. (For an even more detailed treatment of the voice side, see the April 2004 column.) For this example, I'm testing with a slightly simplified example from the Harvard Law RSS site. Notice that I've added an access-control processing instruction to allow browsers which use this processing instruction for access authorization (see W3C Note: Authorizing Read Access to XML Content Using the
Processing Instruction 1.0.)
<?xml version="1.0"?> <?access-control allow="*"?>
<rss version="2.0"> <channel> <title>Liftoff News</title>
<link>http://liftoff.msfc.nasa.gov/</link> <description>Liftoff to Space Exploration.
</description>
<tem>
<Title>Star City</Title>
<Link>http://liftoff.msfc.nasa.gov/news/2003/news-starcity.asp</Link>
<description>How do Americans get ready to work with Russians aboard
the International Space Station? They take a crash course in culture,
language and protocol at Russia's Star City.
</description>
<pubdate<Tue, 03 Jun 2003 09:39:21 GMT</pubdate>
<guide>http://liftoff.msfc.nasa.gov/2003/06/03.html#item573<guide>
</item>
<item>
<title>The Engine That Does More</title>
<link>http://liftoff.msfc.nasa.gov/news/2003/news-VASIMR.asp</link>
<description>Before man travels to Mars, NASA hopes to design new engines that
will let us fly through the Solar System more quickly. The proposed VASIMR engine
would do that.
</description>
<pubDate>Tue, 27 May 2003 08:37:32 GMT</pubDate>
<guid>http://liftoff.msfc.nasa.gov/2003/05/27.html#item571</guid>
</item>
<item>
<title>Astronauts' Dirty Laundry</title>
<link>http://liftoff.msfc.nasa.gov/news/2003/news-laundry.asp</link>
<description>Compared to earlier spacecraft, the International Space Station has many
luxuries, but laundry facilities are not one of them. Instead, astronauts have other options.
</description>
<pubDate>Tue, 20 May 2003 08:56:02 GMT</pubDate>
<guid>http://liftoff.msfc.nasa.gov/2003/05/20.html#item570</guid>
</item>
</channel>
</rss>
|
Apple's developer site has a great article that gives some sample code for pulling in XML data in the visual browsers. Let's borrow that code for our example. We're going to add two lines to put the resultant XML data in a DOM object and call our render function.
// ajax.js
var req;
function loadXMLDoc(url) {
req = false;
// branch for native XMLHttpRequest object
if(window.XMLHttpRequest) {
try {
req = new XMLHttpRequest();
} catch(e) {
req = false;
}
// branch for IE/Windows ActiveX version
} else if(window.ActiveXObject) {
try {
req = new ActiveXObject("Msxml2.XMLHTTP");
} catch(e) {
try {
req = new ActiveXObject("Microsoft.XMLHTTP");
} catch(e) {
req = false;
}
}
}
if(req) {
req.onreadystatechange = processReqChange;
req.open("GET", url, true);
req.send(null);
}
}
function processReqChange() {
// only if req shows "loaded"
if (req.readyState == 4) {
// only if "OK"
if (req.status == 200) {
// ...processing statements go here...
// ADDED THE NEXT TWO LINES
var oDOM = req.responseXML;
renderHTML(oDOM);
} else {
alert("There was a problem retrieving the XML data:\n" +
req.statusText);
}
}
}
|
In VoiceXML, the code to fetch the XML data is a little simpler. Now you have your RSS data loaded in IE, Firefox, or your favorite VoiceXML 2.1 browser! Because the DOM primitives are standardized, you can use your standard code to parse it. The following code works in all browsers.
// parser.js function getChannelTitles(dom) {
var arrTitles = new Array();
var oRoot = dom.documentElement;
if (oRoot.nodeName == "rss")
{
var oChan = oRoot.getElementsByTagName("channel").item(0);
if (oChan != null)
{
var arrItems = oChan.getElementsByTagName("item");
if(arrItems != null)
{
for (var i = 0; i < arrItems.length; i++)
{
var titles = arrItems.item(i).getElementsByTagName("title").item(0);
arrTitles.push(titles.firstChild.data);
}
}
}
}
return arrTitles; }
|
Now that you can access your data, you just need to display it visually or play it in VoiceXML. Here's some simple HTML to display it. Borrowing again from our Apple developer example.
<html> <script src="ajax.js"></script> <script src="parser.js"></script>
<script> //add item to select element the less elegant, but compatible way.
function appendToSelect(select,value,content) { var opt; opt = document.createElement("option"); opt.value = value; opt.appendChild(content); select.appendChild(opt); }
// fill Topics select list with items from // the current XML document function renderHTML(dom) {var select = document.getElementById("topics"); var arrTitles = getChannelTitles(dom);
for (var i=0; i < arrTitles.length; i++) { appendToSelect(select, i, document.createTextNode(arrTitles[i])); } }
|
Now let's play them back in VoiceXML too.
<vxml version="2.1" xmlns="http://www.w3.org/2001/vxml"> <script src="parser.js"/> <form> <block> <data name="oDOM" src="myrss.xml"/> <foreach array="getChannelTitles(oDOM)" item="title"> <value expr="title"/> </foreach> <exit/> </block>
<catch event="error"> <log>feed fetch or access caused <value expr="_event"/></log> Sorry. The requested information is unavailable. Please try again later. </catch> </form> </vxml>
|
There you go! A little AJAX goes a long ways.
Q: I've seen the access-control header for <data> used by some voice browsers. I don't see it described in VoiceXML 2.1 can you tell me more about it?
A: If you're familiar with browser security issues, then you know that web browsers aren't allowed to go poking around just any network resources they can find. You really don't want any website you visit to just start reading stuff from your intranet or your hard drive!
However, this creates a problem for websites that legitimately want to do AJAX-style programming and fetch XML documents from the web. How does the browser decide which XML documents an application can look at (such as public RSS feeds) and which they can't (such as the XML Excel document sitting out on your intranet describing the projected budget!)
Typically browsers restrict applications to only fetch from the domain of the application. So Google Maps can only get data from .
However, if particular XML data that wanted to be shared could say so explicitly ("information wants to be free"), then AJAX-style applications could use them. This way your projected budget doesn't grant any access, but you could say that your RSS feed is open to anyone by putting <?access-control allow="*"> at the top. This technique was pioneered by voice browser vendors as part of the VoiceXML 2.1 <data/> element, but is not restricted to voice browsers. Because the policy was general to all browsers and not a voice-specific functionality, the Voice Browser Working Group decided not to hardcode it into the VoiceXML 2.1 spec. Instead it was published as a NOTE. You can find the documentation here: W3C Note: Authorizing Read Access to XML Content Using the <?access-control? Processing Instruction 1.0 Perhaps other browsers will adopt this too, expanding the universe of data you can use in your AJAX applications!
|