{uccx scripting: write xml doc w/o keyword transform step}

This post was inspired by a conversation on the Cisco Technical Support Forums that was originally pinned in 2007 (fwiw I was still in the US Army then).

Can I write an xml document other than using the template file and keyword tranform step?
I have too many values (1000+) to transform, it would take too long to enter them manually in the keyword transform step…

In my previous post, “automating after hours on-call “engineer” rotation schedules (who has been assigned this role before?), I created an XML Document from the document respository using the Create XML Document Step, Parsed that document for specific values using XPath Expressions in the Get XML Doc Data Step, and then “Wrote to the XML Document”(we’re really “modifying” our XML Document here) using UCCX’s KeyWord Transform Step. In this post we are going to pretend that we cannot process this document the easy way; we are going to “manually” create the XML Document using the JDOM Java Library (UCCX Custom File), I’m going to demonstrate several JDOM Methods to get XML Document Data (some additional stuff for our learning purposes), then we are going to modify some of the XML Document’s Data, so we can then Upload the changes back to the UCCX repository..and thus helping answer the above question..that really was never answered until recently (using String..don’t do it..and the built-in Java DOM Library..hence I’m going to demonstrate a more elaborate and efficient means of doing it..of course this is definitely debatable 🙂

Product: UCCX 8.x + with Enhanced License or better
Scenario: Read Above..
Problem: The Keyword Transform Step GENERATE Entirely New XML files, and in the case of having over 1000 Elements in your XML File as the statement above suggests, if you want to perserve the values of your XML File..you have to create a Keyword for All 1000+ TextNodes for the Elements in the Doc since the Keyword Transform Step CANNOT accept an existing XML Document.
Disclaimer: Consume at your own risk.

If you cannot use the Cisco “built-in” method (Keyword Transform Document) for modifying XML (because of limitations etc), then this post is for you as long as you can connect the dots with your own data..Java offers up many ways to work with XML, and Java developers are a dime a dozen and if there isn’t 1 Post on working with XML in Java there are 100. As a UCCX engineer who might encounter a scenario such as this, the best thing to do is find a resource to help you; however, this is reality and most won’t do that. If you take one thing away from the posts that I concoct in regards to UCCX scripting, the language used is not proprietary and if you perform a simple search on parsing/modifying xml documents with Java you could find the “documentation” you need to solve the problem..outside of the UCCX documentation that I and everyone else for that matter says is lacking; Here is just one example of many you can find.

Since we have to go to Java to get work done, I am going to show you a really handy Java Library I like to use called JDOM. But first we’ll talk a little about the built-in Java Document Object Model Library. I’ve covered this before in previous posts, but the typical builtin library for XML across languages is very similar; in that previous post I covered Python and Java. If you look at JavaScript (where the DOM is alway present because HTML is built on the DOM) accessing and modifying the DOM is pretty much the same syntactically as the other two languages I mentioned. And for the record, I don’t memorize the code needed in order to get a job done. As far as XML is concerned, I know you have the Root Element of a Document: OnCallAgent and then all the Children of the Root are exactly 1 Branch Down from the Root (which makes this document that much easier to parse). So we’ll change the Document we used previously as noted below:

<?xml version="1.0" encoding="ISO-8859-1"?>
<OnCallAgent>
    <Number>6262</Number>
    <WeekOfYear>28</WeekOfYear>
</OnCallAgent>

<!--2 Different Docs-->

<OnCallAgent>
    <AgentDetails>
        <Number>6262</Number>
        <Name>John Doe</Name>
    </AgentDetails>
    <WeekOfYear>28</WeekOfYear>
</OnCallAgent>

In order to use the code I’m going to provide, you need to download jdom2 (I’m using jdom-2.0.5.jar)..I’ll leave a copy of the jar file in the files here. When using external JARs the page where you “activate” them tells you what you need to do after you Upload a file (when you click on Upload Custom Jar Files, the page redirects you to the Document Repository, upload the jar there, then return to Custom Classs Config to make the available class path entry –> selected classpath, then proceed to restart appropriate services):

CustomFileUploadThe documentation for using JDOM to perform XML file work is HERE (parsing, creating, modifying, extracting, et al). The layout is in about the same manner of the typical Java Langugage documentation. To get the process kicked off, first we have create a JDOM document for parsing. For the sake of the script we are going to build, there is one major method we’ll use, but it’s also important to understand at least 2 other methods (in my testcase code I’m leaving you with 3 methods):

//Create Our Parser
org.jdom2.input.SAXBuilder builder =
    new org.jdom2.input.SAXBuilder();
try {
    //Create JDOM DOC by Building it from the Parser
    org.jdom2.Document d =
        builder.build( DOC[onCallAgent.xml].getInputStream() );
catch(org.jdom2.JDOMException jex) {
    //Something Happened
}
//It is good practice to Protype these in a customary
//Java IDE, so you know what Exceptions the Methods
//That are used "Throws"
/*
Other Methods You Might Use
builder.build("http://ccxip:9080/documents/onCallAgent.xml");
builder.build("/opt/cisco/uccx/Documents/User/en_US/d.xml");
I'm leaving others behind in the Code I'll leave you with
*/

Once we have the Document we have to get the Root Element; this allows us to then navigate the “tree-like” structure of the document (DOM).

org.jdom2.Element root = d.getRootElement();
//Interested in the Root Name?
//Gives you an Idea of where you are in the DOC
//Not really needed for what we are doing
String rootName = root.getName();

Let’s take a peak at what the document tree looks like..the image is pretty crude but hopefully you get the point:XMLTree

The root element of this document is OnCallAgent. The children of the root are AgentDetails and WeekOfYear. At this point I should “print” out the Children of the Root for demonstration and to show you an oddity with the “UCCX Expression Language” (it actually hurts me to call it that). For those of you who can program in Java you will understand what I’m referring to with this oddity..just bare with me.

java.util.List elemList = root.getChildren();
String child1 = (org.jdom2.Element) elemList.get( 0 ).
    getName(); //Name
//Cast Element Type on the List.get(int) method
//To then Call the Element.getName() method
String child2 = (org.jdom2.Element)elemList.get(1).getName();
//Number

This may not make any sense to anyone..but I’m going to explain it regardless…In Java 5 and later Java introduced Generics/Parameterized Type for Container Classes such as Lists/ArrayLists et al so the normal method for instantiation is like such: List<Element> eList = root.getChildren(); this syntax allows us to “type” what is added to the List (container) otherwise the default type is java.lang.Object and when that is the case as is above..you have to Cast the Type when extracting the data from within the contents of the List Object..whereas when I call the List.get(int) method I have to Cast it to a JDOM Element because that what is actually returned..and then I can call the Element’s getName() method in order to see what the Value of the First Element in the XML Tree is. Why did I tell you all of that? UCCX doesn’t support Generics, so when you extract the data from the List into the “Type” you know it to be..you have to Cast (how many times did I say that now?).

Next we need to Get XML Document Data (Step) using the appropriate org.jdom2.Element methods. Then we will proceed to modify them. To modify them we have to get the appropriate ElementsName/ and Number/. Check it out below.

//Walk the TREE Branch by Branch
String sName = root.getChild("AgentDetails").
    getChild("Name").getText();
String sNum = root.getChild("AgentDetails").
    getChild("Number").getText();
String sWoy = root.getChild("WeekOfYear").getText();
//Modify Appropriate Elements
nameElem = root.getChild("AgentDetails").getChild("Name").
    setText("Jane Smith");
numElem = root.getChild("AgentDetails").getChild("Number").
    setText("9999");
//"Reassign" Value of our String(s)
sName = nameElem.getText();
sNum = numElem.getText();
//It might be easier to get the "agentDet" Element

We’re still not finished..Now we need to take the Document we have been working on and convert it into a com.cisco.doc.Document so it can be uploaded to the Document repository just like in the previous post..

org.jdom2.output.XMLOutputter out =
    new org.jdom2.output.XMLOutputter();
dOnCallAgent = TEXT[ out.outputString( d ) ];

I’m leaving you with all the code (plus the jdom jar file and the relevant XML file needed as before: OnCallAgent.xml)…First I have a “scratch” pad for demonstration (yes this is a uccx script)..the code in this scratch pad is runnable as long as you have a uccx system with the proper license, the JAR File, and time of course..The other item I have is the previous posts’ script but using JDOM instead of the build-in uccx xml steps; I’m not going to demonstrate how’s it has been modified..if you would like to play with it and/or use it..please play and use at your own risk..Our Next Post concerning this (unless I get distracted) is to take all the “exposed raw” code that I have written and JAR it:  AF_JDOM_Files

return sam;

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s