CallXML 3.0 Development Guide Home  |  Frameset Home

  C: CallXML Variables  |  TOC  |  E: Exceptions & Errors  

Appendix D: Best Practices

This series of documents will cover the suggested best practices that will allow you to write superior CallXML applications with a minimum of hassle. We will cover the optimal coding techniques that will ensure that your applications run smooth as glass, and as Cool As Ice. While not a complete dissertation of the CallXML language, this guide should serve as a good starting point for your CallXML application tuning needs.


Container Element Enhancements

CallXML 3.0 adds a few new container aliases to work with in our applications, which can assist greatly in syntactical operations, and code 'readability'. These new elements differ only in name; for all practical purposes, these new element aliases are completely identical. The naming semantics of these new elements allows the developer to christen particular sections of code based on the operations that are performed within them, thus making it much easier to interpret application flow at a glance. The listing of these container elements is as follows:


The possible attributes allowable for these containers are conveniently listed below:



Again, there is absolutely no difference between the functionality of these elements other than the names themselves. To illustrate this point even further, one can declare with authority that the below snippets of code are indeed indistinguishable from one another in terms of execution, and in terms of possible child attributes that one can include within the element declaration:

<block> element

<block label="B1" value-is="foo">
..
</block>


<case> element


<case label="B1" value-is="foo">
..
</case>


<with> element

<with label="B1" value-is="foo">
..
</with>



So how does this help the developer, exactly? Let's take a look at an example that uses four container <block> elements in a slightly different way:



<block choices="red, green, blue">
  <say>you can choose red, green, or blue</say>
</block>

<block foreach="first, second, third" var="i">
  <say> this is the $i; time i'll say something</say>
</block>

<block test="1=1">
  <say>one does equal one</say>
</block>



So, is there anything actually wrong with this code? Absolutely not. Map it, then test it, and it will execute normally. However, it might not be immediately evident what these different <block> elements are doing when scrolling through a document that contains a large amount of these ambiguous container elements. Although, it is much easier to read and intuit the code at a glance by writing the code as we have in our second example:


<with choices="red, green, blue">
  <say>you can choose red, green, or blue</say>
</with>

<block foreach="first, second, third" var="i">
  <say> this is the $i; time i'll say something</say>
</block>

<if test="1=1">
  <say>one does equal one</say>
</if>


Of course, you can pick and choose whichever naming scheme best suits the coding style you prefer for your application. After all, what we have detailed here is simply illustrating the syntactic 'sugar' that allows for easier readability and comprehension of your CallXML code.

However, do not fall into the assume that just because the element names are similar to existing ones in other markup languages, that they do not need to obey CallXML-specific rules. For instance, changing a <block> to a <loop> does not imply that we can perform complex JavaScript operations within the element, nor does it imply that CallXMl scoping , or nesting rules no longer apply. Down deep in the  Application Gateway Software, <loop> equals <foreach><block> equals <block> in all ways, shapes, and forms.


Attribute Inheritance From Container Elements

Another new feature that we have included within the CallXML3.0 markup is the ability to specify a 'value' attribute for a container, which will then inherently populate any enclosed value/choice attributes that are left unspecified. This provides convenient shorthand that saves development time. To explain, we can automatically fill in values for the elements/attributes listed below with a single container 'value' specification:


<callxml version="3.0">
<do value="foo.wav" choices="bar">
  <say />
  <wait value="5s"/>
  <log />
  <playaudio />


  <on event=" choice=bar">
  <log> !!!!! bar event is caught !!!!! </log>
  </on>

  </do>
</callxml>


Note that we have not defined any attributes for the <playaudio>, <say>, or  <log> elements, but at runtime, the CallXML will execute as follows:


<callxml version="3.0">
<do value="foo.wav" choices="bar">
  <say choices="bar"/>
  <wait value="5s" choices="bar"/>
  <log value="foo.wav"/>
  <playaudio value="foo.wav"/>


  <on event="choice=bar">
  <log> !!!!! bar event is caught !!!!! </log>
  </on>

  </do>
</callxml>



From comparing the two bits of sample code, it is fairly apparent that the container-level 'value' attribute inherently populates the unspecified 'value' attributes of the <say>, <log>, and <playaudio> elements. The same is true for the container-level 'choices' attribute tacking on its values to the <wait> and <say> elements. Obviously, this is a very simple example illustrating the conceptual uses of container inheritance, but with a little creativity, one can see the myriad possibilities that exist for this new feature.


List Iteration With Container Elements

The last of the new container element features to discuss is the inclusion of the new 'foreach' attribute, which is available on all of our new container aliases. As its name suggests, this attribute allows the developer to specify a list of values that can be iterated, (or 'looped'), through as the application executes.  For instance, let's assume that we have an array of values returned from a database call, and we wish to output these values via the <playaudio> element within the CallXML application. For simplicity's sake, these values will be sequential numeric values that will indicate a countdown:



  <callxml version="3.0">
        <with foreach="10.wav, 9.wav, 8.wav, 7.wav, 6.wav, 5.wav, 4.wav, 3.wav, 2.wav, 1.wav" var="countdown">
            <playaudio value="$countdown;"/>
            <log value="$countdown;"/>
            <wait value="1s"/>
        </with>

        <do>
          <say>
            liftoff!
          </say>
        </do>

    </callxml>


When we run this code, the files "10.wav" through "1.wav" will be played to the caller in order, with the log values for each iteration showing up sequentially in the debugger as well. This saves time and makes for cleaner code, considering that if we wanted to do the same thing with CallXML2.0, we would have needed a separate <playaudio> tag defined for every audio file we meant to output, as well as having to code our array looping on the backend, (as opposed to doing it within the CallXML context).


Case Sensitivity

CallXML 3.0 is case sensitive -- all element and attributes must be in lowercase, not mixed case or upper case, as illustrated below:

Valid:


<playaudio>
<getdigits>
<on event=choice:1">


Invalid:


<hl>PlayAudio>
<getDigits>
<on event Choice="1">


Element Nesting and Navigation

Nesting is allowed with block elements, but care needs to be excercised when creating navigation logic. Navigation is not allowed to nested blocks when the initializing block sits outside of the nesting block's scope; i.e.:


<?xml version="1.0" encoding="UTF-8"?>
<callxml version="3.0">

  <block label="B0" next="#D2">
    <log value="**** ENTERING B0 ****"/>

    <do label="D1" next="#D2">
      <log value="**** ENTERING D1 ****"/>
    </do>

    <do label="D2" next="#D4">
      <log value="**** ENTERING D2 ****"/>
    </do>

    <do label="D3">
      <log value="**** ENTERING D3 ****"/>
    </do>

  </block>

  <do label="D4" next="#D3">
<!-- This 'next' target of '#D3' will never be executed, -->
<!-- as it sits outside of the nested block scope -->
    <log value="**** ENTERING D4 ****"/>
  </do>


Be aware that using <goto next> in place of the 'next' container element attribute  will not function for navigation between nested containers. Therefore, it is recommended that you not use the <goto> element within your code unless transitioning to an entirely separate page, or submitting variables is required by your application.

Also note that any subsequent documents will not be able to 'see' nested containers as valid navigation identifiers. For example, if we were in another document, then having a <goto> or <do next> target of 'MyDoc.xml#B3' would throw an 'event: error "document" (invalid target for goto or next attribute)' message to the Voxeo Logger.


Order of Execution

For consistency, the behavior of actions following event handlers inside of a container element or one if it's many aliases has changed. Previously actions following event handlers could be executed in some situations. With CallXML versions 2.0 and above, they will not be executed, as evidenced below:



<callxml version="3.0">

  <do>
    <say>please leave your message.</say>
    <recordaudio value="mailto:bob@home.com" maxsilence="4s" maxtime="45s"/>
      <on event="maxsilence">
      <log>*** MAXSILENCE EVENT OCCURRED ***</log>
      </on>
      <on event="maxtime">
      <log>*** MAXSILENCE EVENT OCCURRED ***</log>
      </on>
    <prompt value="thank you">
  </do>

  <do>
    <playaudio value="holdmusic.wav"/>
  </do>

</callxml>


In CallXML 2.0+, the 'thankyou.wav' file will never be played, however the 'holdmusic.wav' file will always be played in both CallXML 2.0 and 3.0.


Telephony Event Handling

When writing an application with <onanswer> or <reject> elements, note that best practices dictate that you immediately transition to a new starting block, else we run the risk of other handler events not getting properly executed. Nesting the contents of your entire CallXML document within an <on event="answer"> element is also inadvisable for the very same reason. For example, the following code sample shows that neither the <block> nor the <say> element will ever be executed:


<?xml version="1.0" encoding="UTF-8"?>
<callxml version="3.0">
  <on event="answer">

    <do label="D1" repeat="3">
      <say choices="*"> press the star key now </say>

      <on event="choice:*">
        <log value="*** USER PRESSED STAR ***"/>
      </on>

    </do>

  </on>
</callxml>


However, 'smart' coding dictates that we would structure our document like what we have below in order to get the functionality that we want:


<?xml version="1.0" encoding="UTF-8"?>
<callxml version="3.0">
  <on event="answer">
    <goto value="#D1"/>
  </on>

  <do label="D1" repeat="3">
      <say choices="*"> press the star key now </say>

      <on event="choice:*">
        <log value="*** USER PRESSED STAR ***"/>
      </on>

  </do>

</callxml>





  ANNOTATIONS: EXISTING POSTS
0 posts - click the button below to add a note to this page

login
  C: CallXML Variables  |  TOC  |  E: Exceptions & Errors  

© 2012 Voxeo Corporation  |  Voxeo IVR  |  VoiceXML & CCXML IVR Developer Site