ServiceNow has come yet another step closer to making it easier to consume web services (or other XML based API’s) and quickly create records based off of the XML data that is returned. In the Winter 2011 release, ServiceNow quietly introduced a library that allows a script to convert an XML string into a record in any table in the system.
We’re going to go through a simple example of how you might do this. The example I am creating was written in the “Background Scripts” module of my test instance. You can do the same, or your can create a business rule or other script to test this out.
For this example, I am going to generate an XML string on the fly. Normally, you would be receiving this XML string from a SOAP web service or other API that you are consuming. To keep this simple, however, we will just generate some XML to test the new library.
1 2 3 4 5 6 7 8 9 10 11 12 13 | //Set up the XML string var xml = "<xml>"; var template = "<cmdb_ci_server><asset_tag>___ASSETTAG</asset_tag><name>___NAME</name><operational_status>1</operational_status><order_date/><os>Linux Red Hat</os><os_version>Enterprise Server 3</os_version><short_description>A Test CI for XML based Record Generation</short_description></cmdb_ci_server>"; // Generate a number of Configuration Items within the XML. var numOfItemsToCreate = 15; for(var i=0; i<numOfItemsToCreate; i++){ xml += template.replace("___ASSETTAG", "JJATAG_"+i).replace("___NAME", "JJANAME_"+i); } //Finish up the XML string xml += "</xml>"; |
What this bit of code did was create a variable called “xml”. It also creates a variable called “template”. The “template” variable stores an XML node that contains elements in the node that have the name name as elements in my table. Typically our destination table would be an Import Set Table. Once we are finished running this script, we would have an XML string that looks like the string below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | <xml> <cmdb_ci_server> <asset_tag>JJAATAG_0</asset_tag> <can_print>false</can_print> <cd_rom>false</cd_rom> <name>JJAANAME_0</name> <operational_status>1</operational_status> <order_date/> <os>Linux Red Hat</os> <os_version>Enterprise Server 3</os_version> <short_description>Glide Production </short_description> </cmdb_ci_server> <cmdb_ci_server> <asset_tag>JJAATAG_1</asset_tag> <can_print>false</can_print> <cd_rom>false</cd_rom> <name>JJAANAME_1</name> <operational_status>1</operational_status> <order_date/> <os>Linux Red Hat</os> <os_version>Enterprise Server 3</os_version> <short_description>Glide Production </short_description> </cmdb_ci_server> <cmdb_ci_server> <asset_tag>JJAATAG_2</asset_tag> <can_print>false</can_print> <cd_rom>false</cd_rom> <name>JJAANAME_2</name> <operational_status>1</operational_status> <order_date/> <os>Linux Red Hat</os> <os_version>Enterprise Server 3</os_version> <short_description>Glide Production </short_description> </cmdb_ci_server> <cmdb_ci_server> <asset_tag>JJAATAG_3</asset_tag> <can_print>false</can_print> <cd_rom>false</cd_rom> <name>JJAANAME_3</name> <operational_status>1</operational_status> <order_date/> <os>Linux Red Hat</os> <os_version>Enterprise Server 3</os_version> <short_description>Glide Production </short_description> </cmdb_ci_server> <cmdb_ci_server> <asset_tag>JJAATAG_4</asset_tag> <can_print>false</can_print> <cd_rom>false</cd_rom> <name>JJAANAME_4</name> <operational_status>1</operational_status> <order_date/> <os>Linux Red Hat</os> <os_version>Enterprise Server 3</os_version> <short_description>Glide Production </short_description> </cmdb_ci_server> </xml> |
Since our XML string has a list of records within the XML, we need to determine just how many records are contained in the xml string. In order to do this, I am going to use the XMLDocument library (see Script Includes -> XMLDocument). We will first use XPATH on the root node to get all of the nodes under that root. In our example, the record nodes are contained in the “/xml” root node. We get the number of the records inside of “/xml” by using the following code:
1 2 3 4 | //Determine how many Records are in the XML string (as if we didn't already know) xmlDoc = new XMLDocument(xml); var nodes = xmlDoc.getNodes("/xml/*"); var numCIs = nodes.getLength(); |
Now that we have the number of records that we will want to load into our table, we will need to instantiate the new “ImportSetUtil” library that was created to do this work for us.
1 2 | //Load the ImportSetUtil library...this will do the record population for us var isUtil = new ImportSetUtil(); |
The method that we will use inside of this new library is the “loadFromXML” method. That method takes three parameters:
- XPATH string that points to the root of the element node list that contains each record data item
- The XML Document of our incoming data
- The name of the ServiceNow table where the data will be generated
We will iterate through all of the number of records contained in the XML string an call the “loadFromXML” method on each xml element tree that contains one record.
1 2 3 4 | //Load the XML data into a record on the table for(var i=1; i<=numCIs; i++){ var res = isUtil.loadFromXML("/xml/cmdb_ci_server["+i+"]/*", xmlDoc, "cmdb_ci_server"); } |
After executing the entire script, our XML data is loaded into the table as seen in the screen shot below:
nice article john!!!!
thx for sharing 🙂
Thanks ! This article helped me a lot 🙂
Nice article …. 🙂
Nice article John. Came in very useful!
Hi John
Thank you for sharing such a nice article!
Just wondering if you could give some ideas on how to insert records dynamically using table API into staging table. I’ve written a schedule job using which I am getting the records in xml format. However when I am using the code below, I am just not able to get the fields map to my source table. Exact number of records are getting generated however values are not getting mapped, any ideas?
var request = new GlideHTTPRequest
(‘https://instancename.service-now.com/api/now/table/problem’);
request.setBasicAuth(“xxx”,”xxx”);
request.addHeader(‘Accept’,’application/xml’);
var response = request.get();
var body = response.getBody();
gs.log(body);
var xmlDoc = new XMLDocument(body);
var nodes = xmlDoc.getNodes(“/response/*”);
var numCIs = nodes.getLength();
var isUtil = new ImportSetUtil();
for(var i=1; i<=numCIs; i++){
var res = isUtil.loadFromXML("/response/problem["+i+"]/*", xmlDoc, "problem");
}
Thank you for your article.
Pls explain in the same, how can I convert JSON response to a record??
var isUtil = new ImportSetUtil();
var res = isUtil.loadFromXML(“//ServiceNowCreateIncident/*”, xmlDoc, “incident”);
Incident is created successfully, but the return value res is null. it should be sys_id. Does anyone get the sys_id returned? I need send the response with incident number.