Subscribe via E-mail

Your email:

Follow Evergreen Systems

Evergreen Systems Blog

Current Articles | RSS Feed RSS Feed

ServiceNow Tips: XML Document Migration for Service Catalog Items, Knowledge Management Articles

 

I see a lot of documentation that is formatted in XML now. There is often a requirement to migrate documents into one area or another in ServiceNow. Knowledge documents and catalog items are some of the most common areas that require migration and transformation of XML documents from external systems and outside sources.

One challenge that I have had in the past is not having access to the structure of the XML formatted document that I am working with. I have outlined some code below that will assist with documenting the basic format of an XML document. This is critical when transforming the information from the XML tags into fields in a table in ServiceNow. You may even need to know if a particular tag has child tags and/or attributes associated with it, so I have accounted for this as well. 

I have used this code as a base for:

I - Understanding the format of the XML documents in question

II - Parsing data from tags in order to write it to fields in a table 

This code can be run in a stand-alone fashion (from a UI Action) or as part of an Import process. I have found this to be a handy tool when used in the script section of the transform map.

1. Put the string into an XML document. In this case, I was given a list of xml strings in a spreadsheet. These records are loaded into a standard system import set with the XML string stored in the field 'u_xml'. In order to use the xml functions, I had to transfer the XML string into an XML document (and I had to look at the document in order to get the base node, which I need in order to get all the child nodes.  I could do this programmatically, but in this simple case I am assuming that all the documents have the same structure, so the base node should always be consistent:

 

var baseNode = 'SOLUTIONS';

if (baseNode != ''){

     var xmldoc = new XMLDocument(current.u_xml);

 

2. Next I need to get all the child nodes of the base node.  This is stored as an array:

 

     var solu = xmldoc.getNodes(baseNode);

 

Note: ServiceNow logging is sorted by datetime, and since the logging can be hard to interpret (multiple log entries don't always appear sequentially in the log file), I prefer to build one string and then write that one string to the log with all the information I want to pass along.

 

     var logText = 'Parsing document: '+current.u_documentid+'\n  - node list length :: '+solu.getLength();

 

3. For each of the child nodes, I am writing the node name, type and content to variables so that I can write them to the log in a single string ('\n' will put a carriage return in the log for easier reading).

 

     for (i=0;i<solu.getLength();i++) {

           var nodeName = solu.item(i).getNodeName();

           var nodeType = solu.item(i).getNodeType();

           var nodeText = solu.item(i).getTextContent();

           var nodeAttribute = solu.item(i).getAttribute("SECURITY");

           logText += "\n";

           logText += "the node name is "+nodeName+" and the type is "+nodeType+" Security Attribute: "+nodeAttribute+" and the node text is, if any:\n"+nodeText+"\n";

           var nodeChild = getChildren(solu.item(i));

           logText += nodeChild;

     }

 

     logText += 'Completed Parsing document: '+current.u_documentid;

     gs.log(logText);

} else {

     gs.log("Base node not recognized for document "+current.u_documentid);

}

 

4. Each of the child nodes may also have child nodes, so the following function will parse these child nodes and return the same information to the log text string as the previous code.

 

function getChildren(element) {

     var nodes = element.childNodes;

     var chNodeName, chNodeType, chNodeText;

     var chLogText = '';

     gs.log('child node length '+nodes.length);

     for (var i = 0; i < nodes.length; i++) {

           chNodeName = nodes.item(i).getNodeName();

           chNodeType = nodes.item(i).getNodeType();

           chNodeText = nodes.item(i).getTextContent();

           chNodeAttr = nodes.item(i).getAttribute("SECURITY");

           chLogText += 'child node name '+chNodeName+' child node type '+chNodeType+' Security Attribute: '+chNodeAttr+' child node value \n'+chNodeText+'\n';

   }

   return chLogText;

}

 

The result is a list of xml nodes and their children.  This will include the values in each of the nodes, so if you are only trying to get the basic structure of the XML document, it may become cumbersome to try and parse through the actual field content, so you might want to remove the 'nodeText' and 'chNodeText' variables from log text strings in order to simplify the results.

NOTE:  this code is provided with no warranty and is intended only as a sample and should be modified before use in any live system.

 

About the Author:

Jeff Duryea, Solution Architect
Evergreen Systems

Jeff possesses more than 15 years experience including time spent with HP and Peregrine Systems, and most recently at Citi, where he was a Senior Technical Analyst before joining Evergreen in 2011. Jeff is a graduate of the University of Louisianna at Lafayette.