cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
1710
Views
20
Helpful
16
Replies

Uccx java xml document NodeList command

phwang1234
Level 1
Level 1

 

 

I am trying to write script for a callback application which will check if the caller has already left a call for a callback recently. 

The xml will be something like

 

<CallBack>
<Filename>CB.xml</Filename>

<CB>
<DATE>07/02/2020</DATE>
<TIME>12:00</TIME>
<NUM>0400000000</NUM>
<Done>True</Done>
</CB>

<CB>
<DATE>08/02/2020</DATE>
<TIME>11:00</TIME>
<NUM>0288888888</NUM>
<Done>True</Done>
</CB>

<CB>
<DATE>09/02/2020</DATE>
<TIME>13:00</TIME>
<NUM>0388888888</NUM>
<Done>True</Done>
</CB>

<CB>
<DATE>12/02/2020</DATE>
<TIME>12:00</TIME>
<NUM>0400000000</NUM>
<Done>False</Done>
</CB>
</CallBack>

 

I have this set step

try {
javax.xml.parsers.DocumentBuilderFactory factory = javax.xml.parsers.DocumentBuilderFactory.newInstance();
javax.xml.parsers.DocumentBuilder builder = factory.newDocumentBuilder();
org.w3c.dom.Document domDoc = builder.parse(doc_InputFile);
javax.xml.xpath.XPath XPath = javax.xml.xpath.XPathFactory.newInstance().newXPath();
String XpathEval = str_XPATH;
String RESULT = XPath.evaluate("/CallBack/CB[NUM=0400000000]",domDoc);
return RESULT;
}
catch (java.lang.Exception e) {
e.printStackTrace();
}

 

But it only returns the first node from the xml.

U"\n\t07/02/2020\n 12:00\n\t0400000000\n\tTrue\n "

 

So I tried to change it to return a nodelist as below

 

try {
javax.xml.parsers.DocumentBuilderFactory factory = javax.xml.parsers.DocumentBuilderFactory.newInstance();
javax.xml.parsers.DocumentBuilder builder = factory.newDocumentBuilder();
org.w3c.dom.Document domDoc = builder.parse(doc_InputFile);
javax.xml.xpath.XPath XPath = javax.xml.xpath.XPathFactory.newInstance().newXPath();
String XpathEval = str_XPATH;

NodeList nodeList = (NodeList) xPath.compile("/CallBack/CB[NUM=0400000000]").evaluate(domDoc, XPathConstants.NODESET);
for (int i = 0; i < nodeList.getLength(); i++) {
String RESULT = RESULT + (nodeList.item(i).getFirstChild().getNodeValue());
}


return RESULT;
}
catch (java.lang.Exception e) {
e.printStackTrace();
}

 

I am getting an error on the NodeList line "Unable to parse expression; invalid identifier: NodeList.

It maybe I need to declare these but I am not sure of the syntax required

 

org.w3c.dom.Node;

org.w3c.dom.NodeList;

 

Regards,

Paul

16 Replies 16

Hi Paul,

Please look at the attachment with the sample script. It contains your code and it compiles in UCCX. I've made some small changes so it should work for you.

 

And here is the content of modified function to pull the data (all the changes in red):

{	
        try {
		javax.xml.parsers.DocumentBuilderFactory factory = javax.xml.parsers.DocumentBuilderFactory.newInstance();
		javax.xml.parsers.DocumentBuilder builder = factory.newDocumentBuilder();
		org.w3c.dom.Document domDoc = builder.parse(doc_InputFile);
		javax.xml.xpath.XPath XPath = javax.xml.xpath.XPathFactory.newInstance().newXPath();
		org.w3c.dom.NodeList nodeList = (org.w3c.dom.NodeList) XPath.compile("/CallBack/CB[NUM=0400000000]").evaluate(domDoc, javax.xml.xpath.XPathConstants.NODESET);
		int i = 0;
		for (i = 0; i < nodeList.getLength(); i++) {
			String RESULT = RESULT + (nodeList.item(i).getFirstChild().getNodeValue());
		}	

		return RESULT;
	}
	catch (java.lang.Exception e) {
		e.printStackTrace();
		return null;
	}
}
Marek
Web: https://gaman-gt.com

Hi Marek,

 

Thank you for your great help. The nodelist command is now accepted, but I get no results. I'll look into the nodeitem loop commands and fix that up.

 

Regards,

Paul

Anthony Holloway
Cisco Employee
Cisco Employee
I'm curious as to why you're not using the built-in XML parsing steps.

Hi Anthony,

The XML parsing steps only return the first matching node element, it does not handle repeated telephone numbers unless you loop through and parse each element. This file maybe quite large. I think using java will return the matching nodes without the need to loop through. Then I can loop through the results only.

Regards,
Paul

The for loop in the java code to iterate the nodelist, is almost identical to the loop needed without it, like Sean shows in his example. So, in my opinion, it's the same as far as looping goes, but in the java solution it slows down the editor (in my experience) because it has to import all of those non standard libraries.

Hi Anthony,

 

Thank you for your reply. My understanding was that the java code returns only the nodes that matched the telephone number and then I would only loop through the matched nodes (in this case 2). Where as in Sean's solution I would need to loop through  every node for a match and output the result? I could be interpreting that loop incorrectly?

 

Regards,

Paul

Oh, yep, you're right, I didn't even notice his larger iteration over the entire document.

 

How will you qualify "recently" in your check?  Will the data be purged from the XML document regularly, leaving only recently completed callbacks in there?  Thus, if there is a Done record for a calling number in the document, it could be considered recently?

 

If so, then you don't need to loop at all, you could just look for records which have both a Done = True and a NUM equal to the calling number (or callback number or whatever):

 

when = Get XML Document Data (xml, "//CB[Done='True' and NUM='" + calling_number + "']/DATE")
If (when != null && when.trim() != "")
    True
        /* Found a completed callback for this number */
    False

Sean Lynch
Level 7
Level 7

In the interest of replying with UCCX solution to the requirement ( since I don't speak java, or code very much...), I thought this was a fun challenge.

I created a subflow that would return the requested data. It creates an XML document from the data provided, parses each child node for the matching telephone number and returns the callback elements in a variable of type String for tags matching: DATE, TIME, NUM, and Done (in the cases where CallBack Done is 'False').  This will work for 'no,' 'single,' and 'multiple' instances of the telephone number requested, based upon the sample XML format.

It is probably not as efficient as the java code, but this is my [UCCX] solution to the original post:

2020-0217-callbackContactInfo.PNG2020-0217-callbackContactInfo-varList.PNG

Again, this could probably be done more efficiently, and I invite anyone to revise and post.

Hope this helps...

-Sean

Tip: If you use sCB_Done.toLowerCase() == "false" you can eliminate your alternate case condition checks.

Thank you, Anthony. I was looking for that... Guess I didn't scroll down the list far enough. Great share. I always try to cover as many possibilities as feasibly conceivable--sometimes not knowing all of the input parameters. This really helps. And with XML being character/case sensitive, it can be a real 'thorn-in-the-side.'
Many thanks,
-Sean

So, I just found out that we are being limited to XPATH 1.0, since in XPATH 2.0 there exists a lower-case() function, and we can't use it.  You'll get an Exception thrown if you try to use it, saying it does not exist.  That's unfortunate.  XPATH 3.1 is the current spec.

It would also be nice if UCCX could process "boolean" values/responses if a match is found among all childlist tag elements.
(ex. //CB/NUM=0400000000) would return 'true' that the value is in the list of elements. UCCX doesn't like this and throws an exception. Simple queries is all we get... for now. :-/
-Sean

It would be nice.

Hi Sean,

Thank you for your help. I am sorry I forgot to mention that the xml may be quite large, maybe 100 node entries per callback or more. The looping will work but I may run into the step limit issue or resources on the server as I am loading and processing the xml file per callback. So I tried to look into using java code for this part to reduce steps and resource usage.

Regards,
Paul