cancel
Showing results for 
Search instead for 
Did you mean: 
cancel

Arrays CVP Studio

jferris1979
Beginner
Beginner

I'm looking for some suggestions on the best way to handle array's in CVP studio with a web service element.  I'm building an IVR application using CVP.  CVP will make a SOAP request using a Web Service Element to get a list of items a user is allowed to order.  

For example the SOAP request may return something like this:

 

<a:ItemToOrder>

     <a:Name>Item 1 Name</a:Name>

     <a:package1Size>10</a:Package1Size>

     <a:ProductCode>1111</a:ProductCode>

</a:ItemToOrder>

<a:ItemToOrder>

     <a:Name>Item 2 Name</a:Name>

     <a:package1Size>20</a:Package1Size>

     <a:ProductCode>2222</a:ProductCode>

</a:ItemToOrder>

 

There could be 10 items available to caller one and 20 items to caller two, 30 items to caller 3, etc.

 

I need to save this data for later so that when a caller tries to order a item  can then compare the product code with the items in the list they are allowed to order.

 

In the Web Service Element I can configure a number of responses manually for example:

Item[0]

  Name

  Size

  Product Code

Item[1]

  Name

  Size

  Product Code

...etc

 

However this is manual config and I wont know full count of items a caller can order until I run the SOAP request.

 

Does anyone have any Ideas on how to handle this more dynamically?

 

Thanks,

 

James

 

 

 

 

6 REPLIES 6

janinegraves
Rising star
Rising star

Hi - here's a very detailed answer. Lots of steps, but it should work.

 

You can parse it yourself using JavaScript in the Set Value element.

Cisco provides a package to import that contains a method named XpathUtil.eval(xml,xpath)
It takes 2 arguments, an XML string, and an XPath expression.

 

2
However before you can parse it, you'll need to remove all the colons from the markup tags.
That can also be done using JavaScript.

3
In the Soap WS element, select the checkbox next to Response, named Store full response
The return value will be in element data for the rest element {Data.Element.Rest_01.response_xml}
That variable name won't display in the substitution window, you'll have to key it in as response_xml.
You can log it to the Activity Log in the next element's General tab to ensure you've gotten it.

4 Now you must use JavaScript to remove the colons else it's not able to be parsed as XML.
If you haven't used the SetValue element yet, it creates a variable that's a LOCAL VARIABLE (not element or session data).


Using a SetValue element, go to its Settings tab. Right-click and select Add Variable.
Name: LocalXml
Value: {Data.Element.Rest_01.response_xml}.replace(/:/g,"")


That'll remove all the colons and save the result into the Local Variable named LocalXml

5 The variable {LocalVar.LocalXml} looks something like this. I recommend logging it to the Activity Log to be sure you've removed all the weird characters.

<aItemToOrder>
<aName>Item 1 Name</aName>
<apackage1Size>10</aPackage1Size>
<aProductCode>1111</aProductCode>
</aItemToOrder>
<aItemToOrder>
<aName>Item 2 Name</aName>
<apackage1Size>20</aPackage1Size>
<aProductCode>2222</aProductCode>
</aItemToOrder

****** I recommend you stop and test this now. View the Activity Log and be sure the LocalXml looks ok. Otherwise the next step may faile.

6 Now that you know the above worked, you can return to that Set Value element to add another variable to get the size aItemToOrder array.

In the Settings tab, right-click and select Add Variable

Name: LocalNumRows
Value: (it's all case sensitive)
importPackage(com.audium.server.cvpUtil)
var xml = {LocalVar.LocalXml}
var path = "count(//aItemToOrder)"
XpathUtil.eval(xml, path)

7
Now if you wanted to loop through all the array indices, you can use a Counter element.

8
Use a Decision element to check if ElementData Counter_01 count < LocalVariable LocalNumRows - return moreData
Otherwise: done

9
Connect the moreData path to another SetValue element to grab the data you need:
You'll be using an Xpath expression like this: //aItemToOrder[1]/aName (replacing 1 with a variable)
Create the following Local Variable:
Name: LocalItemName
Value:
importPackage(com.audium.server.cvpUtil)
var xml = {LocalVar.LocalXml}
var ctr = {Data.Element.Counter_01.count}
var path = "//aItemToOrder[" + ctr + "]/aName"
XpathUtil.eval(xml, path)

Name: LocalSize
Value:
importPackage(com.audium.server.cvpUtil)
var xml = {LocalVar.LocalXml}
var ctr = {Data.Element.Counter_01.count}
var path = "//aItemToOrder[" + ctr + "]/aPackage1Size"
XpathUtil.eval(xml, path)

10 then play this info to the caller and loop back to the counter element.

 

Thank you for the detailed response!  I'll give this a try and let you know how it goes.

Web Services with dynamic data caused always problems to pull the response to variables. Because In the past I had to deal with this problem when the JavaSript lib was not available, WS'es can not only return arrays but also different types of objects that are optional i the WS data structure (ex. in the financial/banking integration where the customer may have multiple accounts, multiple different products).

 

IIn the past projects used an approach with Custom Elements which I always use it in new projects:

  1. I've created the custom element that makes a SOAP request (including primary and secondary IP address)
  2. I've split the XML in the object structure and for each object type, I've created a Custom Element that is able to pull any simple/base data. I don't use here any available automated parsers to avoid problems (I don't use WSDL files).
  3. All the list elements were mapped (in the Java code) as Array Lists
  4. I've created a Custom Element that is able to check the Array List size
  5. I've created a Custome ELement that is able to pull an object from the array list that can be parsed using elements from step 2.

From the above list only point 2 is something that changes as it depends on the object definition in the WS. Other points can be standardized as Custom Standard Elements. 

 

This approach has some advantages and disadvantages compared to JavaScript approach.

Advantages:

  1. Because you use custom SOAP request you can control the headers that are sent to WS
  2. You don't need any WSDL file for it. CVP has a limitation that all needs to be defined in the single WSDL file. Sometimes the description of the WS is divided into multiple WSDL files.
  3. If the WSDL changes (new fields are added, existing fields are changes) there is no need to rebuild the script as it will always work (as I don't use WSDL parsers)
  4. To pull the data from the object I just only enter the name of the variable in Custom Element
  5. Ability to validate the data structure using custom rules (on the Call Studio and in the element structure)
  6. Ability to capture non-standard exceptions that may occur during parse

Disadvantages:

  1. Time consumption - you need to create Custom Elements which takes more time than creating an XPath query
  2. If you need to add new fields to an object (needed in the script) - you need to jump into the code and make changes
Marek
Web: https://gaman-gt.com

Thanks for the information.  My challenge is not knowing how many products a user may order and my thought was to use a session or local variable for each order/quantity but I'm not seeing how I can create them dynamically it seems the out of box set value element I can statically create variables but not dynamically based on the callers actions.

 

I'm thinking your approach of custom element is they way to go here.  Any chance you can point me to a template to use for a custom WebServices element?