We've Moved! Please visit our new and improved forum over at our new portal: https://portal.plumvoice.com/hc/en-us/community/topics

Response XML processing

Questions and answers about IVR programming for Plum DEV

Moderators: admin, support

Post Reply
w2gi
Posts: 46
Joined: Fri Jun 26, 2009 1:35 pm

Response XML processing

Post by w2gi »

Hello,

I'm working on a simple application and while I can mimic the behavior in a HTML page, when I use similar javascript in a vxml document, I don't seem to get any results.

The application code is the following.

<?xml version="1.0"?>
<vxml version="2.0">
<var name="appkey" expr="'3309B8E6-38D2-315F-A06C-9D7F6129150F'"/>
<var name="display" expr="2"/>
<var name="searchradius" expr="'10|25|50|100'" />
<var name="provider" expr="'vxml'"/>
<var name="loc_idx" expr="0" />
<var name="locations" />
<var name="geoLocs" />
<property name="interdigittimeout" value="3s" />
<property name="maxage" value="10s" />
<script maxage="1s" maxstale="1s" src="http://ivr.where2getit.com/chickfila/ivr/vxml.js" />
<form id="getinput">
<field name="address" type="digits?length=5">
<prompt>
Please enter a five digit zip code
</prompt>
<catch event="nomatch noinput">
I'm sorry, but that is not a valid five digit zip code.
<reprompt/>
</catch>
<filled>
<data namelist="appkey searchradius provider address" name="geoLocs" src="http://ivr.where2getit.com/lite?action=locatorsearch" />
<assign name="document.locations" expr="updateFromResponseXML(geoLocs)" />
<goto next="#results" />
</filled>
</field>
</form>
<form id="results">
<block>
<foreach item="location" array="document.locations">
<log expr="'***** LOCATION DETAIL ' + location.address1" />
</foreach>
</block>
</form>
</vxml>

The 'updateFromResponseXML' I can mimic on this web page, hosted.where2getit.com/chickfila/ivr.html. If you have firebug installed you can single step through the function and see the result array that is returned so I'm confident that it is processing the xml correctly.

If you paste the url from the request generated in the vxml document into your browser, you can see the xml response it gets.

http://ivr.where2getit.com/lite?action= ... ress=92807

The call log detail looks like the following. Since nothing in the foreach loop is executed, I assume that the 'locations' array is empty.

d 30 Sep 2009 11:03:45 AM EDT:
Call Start Event: ANII 2242325546 DNIS 3999 VURL http://us.popproxy.plumgroup.com/plumvp/demo.php
DocumentParser::FetchDocument()
DocumentParser::FetchDocument(http://us.popproxy.plumgroup.com/plumvp/demo.php)
Cache Miss: http://us.popproxy.plumgroup.com/plumvp/demo.php
Attempting to fetch http://us.popproxy.plumgroup.com/plumvp/demo.php
Loading Builtin grammar: builtin:grammar/digits
Loading Builtin grammar: builtin:dtmf/digits
VXI::queue_prompts()
bargein set to true
INPUTMODES set to "DTMF VOICE"
Cache Hit: http://us.popproxy.plumgroup.com/plumvp/audio/demo.wav
Audio segment from the URL audio/demo.wav added to prompt queue
VXI::field_element - activating grammars for form = '$_internalName_161882' formitem = 'ext'
VXI::do_recognition()
PromptManager::Play()
Newly queued prompts are now being played

Wed 30 Sep 2009 11:03:51 AM EDT:
dtmf input: 1892
Found grammar match
hypothesis #0: 1892 (0.9990)
VXI::var_element(name="session_id" expr = "session.id")
VXI::var_element(name="dnis" expr = "session.telephone.dnis")
DocumentParser::FetchDocument(demo.php)
Posted form data is URL encoded
Attempting to fetch http://us.popproxy.plumgroup.com/plumvp/demo.php
DocumentParser::FetchDocument(scratchpad.php/jscarbrough%40where2getit.com/test3)
Cache Miss: http://us.popproxy.plumgroup.com/plumvp ... .com/test3
Attempting to fetch http://us.popproxy.plumgroup.com/plumvp ... .com/test3
Loading Builtin grammar: builtin:grammar/digits?length=5
Loading Builtin grammar: builtin:dtmf/digits?length=5
VXI::var_element(name="appkey" expr = "'3309B8E6-38D2-315F-A06C-9D7F6129150F'")
VXI::var_element(name="display" expr = "2")
VXI::var_element(name="searchradius" expr = "'10|25|50|100'")
VXI::var_element(name="provider" expr = "'vxml'")
VXI::var_element(name="loc_idx" expr = "0")
VXI::var_element(name="locations" expr = "")
VXI::var_element(name="geoLocs" expr = "")
Cache Miss: http://ivr.where2getit.com/chickfila/ivr/vxml.js
Attempting to fetch http://ivr.where2getit.com/chickfila/ivr/vxml.js
VXI::var_element(name="appkey" expr = "'3309B8E6-38D2-315F-A06C-9D7F6129150F'")
VXI::var_element(name="display" expr = "2")
VXI::var_element(name="searchradius" expr = "'10|25|50|100'")
VXI::var_element(name="provider" expr = "'vxml'")
VXI::var_element(name="loc_idx" expr = "0")
VXI::var_element(name="locations" expr = "")
VXI::var_element(name="geoLocs" expr = "")
Cache Hit: http://ivr.where2getit.com/chickfila/ivr/vxml.js
VXI::queue_prompts()
bargein set to true
INPUTMODES set to "DTMF VOICE"
Audio segment added to prompt queue from TTS application/synthesis+ssml for:
---------
<?xml version='1.0'?><speak>
Please enter a five digit zip code to find the closest restaurant location
</speak>
---------
VXI::field_element - activating grammars for form = 'getinput' formitem = 'address'
VXI::do_recognition()
PromptManager::Play()
Newly queued prompts are now being played

Wed 30 Sep 2009 11:03:57 AM EDT:
dtmf input: 92807#
Found grammar match
hypothesis #0: 92807 (0.9990)
Cache Miss: http://ivr.where2getit.com/lite?action= ... 7c50%7c100
Attempting to fetch http://ivr.where2getit.com/lite?action= ... 7c50%7c100
VXI::assign_element(name="document.locations" expr = "updateFromResponseXML(geoLocs)")
VXI::foreach_element()
received event: connection.disconnect.hangup:
VXI::exit_element()
Call End Event
Ending session
Ending Session On Channel 17

Thank you.

Jon

support
Posts: 3632
Joined: Mon Jun 02, 2003 3:47 pm
Location: Boston, MA
Contact:

getting error.badfetch error for IVR

Post by support »

Hi,

About your post, could you please provide us with more information on what "updateFromResponseXML" does for your IVR code?

Also, about the src URL for your IVR tag, <data>, we are unable to access it as we are getting an Error 500 message when opening it up on a web browser.

Regards,
Plum Support
Last edited by support on Wed Feb 24, 2010 11:50 am, edited 5 times in total.

w2gi
Posts: 46
Joined: Fri Jun 26, 2009 1:35 pm

Response XML Processing

Post by w2gi »

The url needs to be a complete post per the example in the original form email.

http://ivr.where2getit.com/lite?action= ... ress=92807

The updateResponseFromXML can be viewed if you load this url in your browser.

http://hosted.where2getit.com/chickfila/ivr/vxml.txt

I created a .txt version so you could view it easily in a browser.

Thanks.

Jon

support
Posts: 3632
Joined: Mon Jun 02, 2003 3:47 pm
Location: Boston, MA
Contact:

update on IVR issue

Post by support »

Hi Jon,

Sorry for not getting back to your IVR post earlier.

Our IVR developers are still taking a look at your IVR code (at mostly http://hosted.where2getit.com/chickfila/ivr/vxml.txt specifically) to track down what could be causing this IVR issue.

We'll provide you with an update once we've tracked this IVR issue down.

Regards,
Plum Support
Last edited by support on Tue Feb 16, 2010 12:13 pm, edited 3 times in total.

support
Posts: 3632
Joined: Mon Jun 02, 2003 3:47 pm
Location: Boston, MA
Contact:

IVR code suggestions

Post by support »

Hi,

There were two main issues with your IVR code.

Firstly, whenever you are accessing NodeList objects you were using array style access, with foo[0] or foo. While HTML browsers may support this, the VXML 2.1 recommendation is to provide access with a foo.item(index) method. We recommend replacing all use of array-style access on our DOM objects with .item(index).

Secondly, you had a programmatic error where you expected to log location.address1, but your IVR code uppercases the tagname before it saves it to the IVR property so you meant to log location.ADDRESS1.

Attached are revised versions of your IVR code with the appropriate changes.

vxml.js

Code: Select all

	function updateFromResponseXML(responseXML) {
		var xml		= getCollection(responseXML);
		var node	= findDeepestElement(xml);
		var tagName	= node ? node.parentNode.tagName : null;						
		if (!tagName) return false;
	  
		var nodes	= xml.getElementsByTagName(tagName);
		var attributes	= parseAttributes(xml);
		var records	= parseNodes(nodes);
		return records;
	}
	/**
	 * @method
	 * @param {Array(XMLNode)} nodes
 	 * @return {Array(Object)}
	 */
	function parseNodes(nodes) {	
		var objs = [];
		for(var i=0, len=nodes.length; i<len; i++) {		
			objs[i] = this.parseNode(nodes.item(i), '' + (i + 1));
		}
		return objs;
	}				
					
	/**
	 * @method
	 * @param {XMLNode} node
	 * @param {String} recnum (optional)
	 * @return {Object}
	 */
	function parseNode(node, recnum) {		
		var elements = node.getElementsByTagName('*');
		var obj = {};
		for(var len=elements.length, i=0; i<len; i++) {
			var value = this.getNodeValue(elements.item(i)) || '';
			obj[elements.item(i).tagName.toUpperCase()] = value;			
		}		
		if (!obj.RECNUM && recnum) obj.RECNUM = recnum;
		if (!obj.POINUM && recnum) obj.POINUM = recnum;
		return obj;
	}
	
	/**
	 * @method
	 * @param {XMLNode} xml
	 * @param {Integer} index (optional)
	 * @return {String}
	 */
	function getCollectionName(xml, index) {
		return xml.getElementsByTagName('collection')[index || 0].getAttribute('name');
	}
	
	/**
	 * @method
	 * @param {XMLNode} xml
	 * @param {String} name (optional)
	 * @return {Array(XMLNode)}
	*/
	function getCollection(xml) {
		var cols = xml.getElementsByTagName('collection');
		return cols.item(0);
	}

	/**
	 * @method
	 * @param {XMLNode} node
	 * @return {Object}
	 */
	function findDeepestElement(node) {
		if (!node || !node.hasChildNodes())	//change made to help fix "&" xml problems
			return null;
		var lastElement = null;			
		for(var i=0; i<node.childNodes.length; i++) {
			var childNode  = node.childNodes.item(0);
			if (childNode.nodeType == 1) {
				lastElement = this.findDeepestElement(childNode) || childNode;										
				break;
			}
		}
		return lastElement;
	}
		
	/**
	 * @method
	 * @param {XMLNode} node
	 * @return {String} The text value of the given node
	 */
	function getNodeValue(node) {
	    if (node == null) return null;
// Les 	return node.firstChild ? node.firstChild.nodeValue : node.nodeValue;
	
		if (!node.firstChild) return node.nodeValue;
		if (node.childNodes.length <= 1) return node.firstChild.nodeValue;		
		var value = '';
		for (i=0; i<node.childNodes.length; i++) {
			value += node.childNodes.item(i).nodeValue;
		}
		return value;	
	}
		
	/**
	 * @method
	 * @param {Object} node
	 * @param {Boolean} excludeRoot
	 * @return {String}
	 */
	function toString(node, excludeRoot) {
		var buff = [];				
		if (node.nodeType == 1) {
			if (!excludeRoot) {
				buff.push('<');
				buff.push(node.tagName.toLowerCase());	
				for(var i=0; i<node.attributes.length; i++) {
					if (node.attributes.item(i).nodeValue == '')
						continue;
					buff.push(' ');	
					buff.push(node.attributes.item(i).nodeName.toLowerCase());	
					buff.push('="');	
					buff.push(node.attributes.item(i).nodeValue);
					buff.push('"');						
				}
				buff.push('>');		
			}
			for(var i=0; i<node.childNodes.length; i++) {
				var childNode = node.childNodes.item(i);
				buff.push(this.toString(childNode));
			}
			if (!excludeRoot) {			
				buff.push('</');
				buff.push(node.tagName.toLowerCase());	
				buff.push('>');
			}					
		}		
		else if (node.nodeType == 3) {
			buff.push(node.nodeValue);	
		}
		return buff.join('');
	}
	
	/**
	 * @method
	 * @param {XMLNode} xml
	 * @return {Object}
	 */
	function parseAttributes(xml) {
		var obj = {};
		for(var i=0, len=xml.attributes.length; i<len; i++) {		
			var attr = xml.attributes.item(i);
			obj[attr.nodeName.toUpperCase()] = attr.nodeValue;		
		}
		return obj;	
	}
VXML:

Code: Select all

<?xml version="1.0"?> 
<vxml version="2.0"> 
<var name="appkey" expr="'3309B8E6-38D2-315F-A06C-9D7F6129150F'"/> 
<var name="display" expr="2"/> 
<var name="searchradius" expr="'10|25|50|100'" /> 
<var name="provider" expr="'vxml'"/> 
<var name="loc_idx" expr="0" /> 
<var name="locations" /> 
<var name="geoLocs" /> 
<property name="interdigittimeout" value="3s" /> 
<property name="maxage" value="10s" /> 
<script maxage="1s" maxstale="1s" src="http://ivr.where2getit.com/chickfila/ivr/vxml.js" /> 
<form id="getinput"> 
<field name="address" type="digits?length=5"> 
<prompt> 
Please enter a five digit zip code 
</prompt> 
<catch event="nomatch noinput"> 
I'm sorry, but that is not a valid five digit zip code. 
<reprompt/> 
</catch> 
<filled> 
<data namelist="appkey searchradius provider address" name="geoLocs" 
  src="http://ivr.where2getit.com/lite?action=locatorsearch" /> 
<assign name="document.locations" expr="updateFromResponseXML(geoLocs)" /> 
<goto next="#results" /> 
</filled> 
</field> 
</form> 
<form id="results"> 
<block> 
<foreach item="location" array="document.locations"> 
<log expr="'***** LOCATION DETAIL ' + location.ADDRESS1" /> 
</foreach> 
</block> 
</form> 
</vxml>
Last edited by support on Tue Feb 16, 2010 12:14 pm, edited 2 times in total.

w2gi
Posts: 46
Joined: Fri Jun 26, 2009 1:35 pm

Follow up

Post by w2gi »

Hello,

Thank you for the follow up on this. I'm afraid I would have been searching a long time in the W3C specs for that one. We'll proceed from here.

Thanks again.

Jon

Post Reply