XML parsing with nodes
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎07-31-2015 05:46 PM
I have hit a roadblock with XML parsing with nodes and looking for some help.
I have a rest call that unfortunately only replies in XML.
So my payload looks something like this:
<HOST_LIST_OUTPUT>
<RESPONSE>
<HOST_LIST>
<HOST>
<ID>123456789</ID>
<IP>192.168.0.1</IP>
<TRACKING_METHOD>IP</TRACKING_METHOD>
<DNS>thisServer.domain.com
</DNS><NETBIOS>thisServer</NETBIOS>
<OS>WinBlows2012</OS>
</HOST>
<HOST>
<ID>65498125</ID>
<IP>192.168.0.2</IP>
<TRACKING_METHOD>IP</TRACKING_METHOD>
<DNS>thisPrinter.domain.com</DNS>
<OS>LazerJett</OS>
</HOST>
<HOST>
<ID>984616741</ID>
<IP>192.168.0.3</IP>
<TRACKING_METHOD>IP</TRACKING_METHOD>
</HOST>
</HOST_LIST>
</RESPONSE>
</HOST_LIST_OUTPUT>
I am using XMLDocument2() to parse the XML
data:var xmlDoc = new XMLDocument2();
xmlDoc.parseXML(responseBody);
Able to get the first node:
var nodeOne = xmlDoc.getFirstNode("/HOST_LIST_OUTPUT/RESPONSE/HOST_LIST/HOST");
But unable to get the child nodes from nodeOne by name.
I have looked through:
http://wiki.servicenow.com/index.php?title=Scoped_XMLNode_API_Reference#getChildNodeIterator.28.29
and
https://developer.servicenow.com/app.do#!/api_doc?to=method_class__getchildnodeiterator___xmlnode
But it all relates to getting the first node or the first occurrence or last.I need to be able to set HOST as the "node" indicator, and then search for ID, IP, TRACKING_METHOD, DNS, NETBIOS, and OS for that node only, then move onto the next node, then the next and so on. As shown above there are instances where some of the child nodes may not be present so i cant just say the first child node is this and the second is that.
I have tried making the node.toString(), then .match(/<ID>.*/i) for each value. but when i try to insert the data in to a new GlideRecord it flips out and says that the values are undefined.
If anyone can point me in the right direction i would really appreciate it.
- Labels:
-
Integrations
-
Scripting and Coding
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎08-02-2015 07:47 PM
Here is one way of iterating through them:
var xmlDoc = new XMLDocument2();
xmlDoc.parseXML(xmlString);
//grab HOST_LIST node
var hostList = xmlDoc.getNode('//HOST_LIST');
//iterate through the child nodes
var iter = hostList.getChildNodeIterator();
//gs.info(hostList.getTextContent());
while(iter.hasNext()){
var n = iter.next();
gs.info('Node name: ' + n.getNodeName());
//Outputs all child node values of each HOST
gs.info('Node Text Content (values): ' + n.getTextContent());
gs.info('Node value (xml string): ' + n);
}
If you know that three HOSTs will always come back then another way is to do something like this:
var host1 = xmlDoc.getNode('//HOST');
var host2 = xmlDoc.getNode('//HOST[2]);
var host3 = xmlDoc.getNode('//HOST[3]);
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎08-03-2015 06:19 PM
Chris thank you so much for your help. The part I needed was the .getTextContent().
Here is what i have done so far.
Since the nodes could contain 3-5 child nodes i created a series of "if" statements to see which child node i have landed on and then map that value to a correct variable:
var node = xmlDoc.getNode('//HOST');
//gs.log(node.toString());
var iter= node.getChildNodeIterator();
//vars for mapping
var id = '';
var ip = '';
var track = '';
var dns = '';
var net = '';
var os = '';
while(iter.hasNext){
var n = iter.next();
//gs.log('Node name: ' + n.getNodeName());
var name = n.getNodeName();
if(name === 'ID'){
id = n.getTextContent();
gs.log("ID is: " + id);
}
if(name === 'IP'){
ip = n.getTextContent();
gs.log("IP is: " + ip);
}
if(name === 'TRACKING_METHOD'){
track = n.getTextContent();
gs.log("Track is: " + track);
}
if(name === 'DNS'){
dns = n.getTextContent();
gs.log("DNS is: " + dns);
}
if(name === 'NETBIOS'){
net = n.getTextContent();
gs.log("NetBios is: " + net);
}
if(name === 'OS'){
os = n.getTextContent();
gs.log("OS is: " + os);
}
}
This brings me a nice clean output of my vars = the data from the child nodes or null if there was no value for it.
Now the fun part. You mentioned using:
var host1 = xmlDoc.getNode('//HOST');
var host2 = xmlDoc.getNode('//HOST[2]);
var host3 = xmlDoc.getNode('//HOST[3]);
How would i go about iterating through that using a for loop?
for(var i = 0; i < what goes here????;i++){
var node = xmlDoc.getNode('//HOST[i]');
I tired:
for(var i = 0; i < node.length;i++){
var node = xmlDoc.getNode('//HOST[i]');
but that returned nothing.
I don't really know which variable is the array, or if one really exists here.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎08-03-2015 07:18 PM
While i did not find a way to use a for loop to iterate through HOST[i] i did how ever manage to leverage the getFistNode and getNextNode to run through all nodes.
It is not pretty but here it is, if you have a better, cleaner, faster way to accomplish this i would appreciate it:
//Parsing the Response
var xmlDoc = new XMLDocument2();
xmlDoc.parseXML(responseBody);
//vars for mapping
var id = '';
var ip = '';
var track = '';
var dns = '';
var net = '';
var os = '';
//Grab the first node
var node = xmlDoc.getFirstNode('//HOST');
var iter= node.getChildNodeIterator();
//Run thru child nodes to find what we want
while(iter.hasNext()){
var n = iter.next();
var name = n.getNodeName();
if(name === 'ID'){
id = n.getTextContent();
gs.log("ID is: " + id);
}
if(name === 'IP'){
ip = n.getTextContent();
gs.log("IP is: " + ip);
}
if(name === 'TRACKING_METHOD'){
track = n.getTextContent();
gs.log("Track is: " + track);
}
if(name === 'DNS'){
dns = n.getTextContent();
gs.log("DNS is: " + dns);
}
if(name === 'NETBIOS'){
net = n.getTextContent();
gs.log("NetBios is: " + net);
}
if(name === 'OS'){
os = n.getTextContent();
gs.log("OS is: " + os);
}
}
//Grab the next Node
var nodeNext = xmlDoc.getNextNode(node);
var iter= nodeNext.getChildNodeIterator();
//Run thru child nodes to find what we want
while(iter.hasNext()){
var n = iter.next();
var name = n.getNodeName();
if(name === 'ID'){
id = n.getTextContent();
gs.log("ID is: " + id);
}
if(name === 'IP'){
ip = n.getTextContent();
gs.log("IP is: " + ip);
}
if(name === 'TRACKING_METHOD'){
track = n.getTextContent();
gs.log("Track is: " + track);
}
if(name === 'DNS'){
dns = n.getTextContent();
gs.log("DNS is: " + dns);
}
if(name === 'NETBIOS'){
net = n.getTextContent();
gs.log("NetBios is: " + net);
}
if(name === 'OS'){
os = n.getTextContent();
gs.log("OS is: " + os);
}
}
//Loop thru all nodes
while(nodeNext){
node = nodeNext;
var nodeNext = xmlDoc.getNextNode(node);
//Hit the breaks before you find a wall
if(nodeNext === null) {
break;
}
var iter= nodeNext.getChildNodeIterator();
while(iter.hasNext()){
var n = iter.next();
var name = n.getNodeName();
if(name === 'ID'){
id = n.getTextContent();
gs.log("ID is: " + id);
}
if(name === 'IP'){
ip = n.getTextContent();
gs.log("IP is: " + ip);
}
if(name === 'TRACKING_METHOD'){
track = n.getTextContent();
gs.log("Track is: " + track);
}
if(name === 'DNS'){
dns = n.getTextContent();
gs.log("DNS is: " + dns);
}
if(name === 'NETBIOS'){
net = n.getTextContent();
gs.log("NetBios is: " + net);
}
if(name === 'OS'){
os = n.getTextContent();
gs.log("OS is: " + os);
}
}
}
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎08-10-2016 10:09 PM
Hi Carlos,
I had similar requirement and below was my approach and it worked for me. just have a look and let see if it helpful for you.
Payload format:
<s:Body>
<GetDetailsResponse>
<GetDetailsResult>
<Classifications>
<Classification>
<StartDate>2012-10-02</StartDate>
<PurposeCode>01</PurposeCode>
<SchemeCode>01</SchemeCode>
<ValueCode>411411</ValueCode>
</Classification>
<Classification>
<StartDate>2012-10-02</StartDate>
<PurposeCode>01</PurposeCode>
<SchemeCode>02</SchemeCode>
<ValueCode>3411-11</ValueCode>
</Classification>
<Classification>
<StartDate>2012-10-02</StartDate>
<PurposeCode>01</PurposeCode>
<SchemeCode>04</SchemeCode>
<ValueCode>0603</ValueCode>
</Classification>
<Classification>
<StartDate>2012-05-07</StartDate>
<PurposeCode>01</PurposeCode>
<SchemeCode>05</SchemeCode>
<ValueCode>421</ValueCode>
</Classification>
<Classification>
<StartDate>2012-05-07</StartDate>
<PurposeCode>01</PurposeCode>
<SchemeCode>06</SchemeCode>
<ValueCode>11</ValueCode>
</Classification>
</Classifications>
</GetDetailsResult>
</GetDetailsResponse>
</s:Body>
-----------------------------------------------------------------------------------------------------------------
Script:
var xmlDoc = new XMLDocument2();
xmlDoc.parseXML(responseBody);
var compList = xmlDoc.getNode("//Classifications");
var iter = compList.getChildNodeIterator();
while(iter.hasNext())
{
var n = iter.next();
var abc = '';
var xmlDoc1 = new XMLDocument2();
xmlDoc1.parseXML(n);
var node = xmlDoc1.getNode('//Classification');
var iter1= node.getChildNodeIterator();
while(iter1.hasNext())
{
var n1 = iter1.next();
abc = abc + "\n " +n1.getNodeName()+ " : "+n1.getTextContent();
//gs.log('Node name: ' + n1.getNodeName() + 'Node value: ' + n1.getTextContent() , "XML");
}
gs.log("ABC "+abc, 'Anil');
}
-----------------------------------------------------------------------------------------------------------------
Logs (debug):
Information | ABC StartDate : 2012-05-07 PurposeCode : 01 SchemeCode : 05 ValueCode : 421 | XML | |
Information | ABC StartDate : 2012-05-07 PurposeCode : 01 SchemeCode : 06 ValueCode : 11 | XML | |
Information | ABC StartDate : 2012-10-02 PurposeCode : 01 SchemeCode : 04 ValueCode : 0603 | XML | |
Information | ABC StartDate : 2012-10-02 PurposeCode : 01 SchemeCode : 01 ValueCode : 411411 | XML | |
Information | ABC StartDate : 2012-10-02 PurposeCode : 01 SchemeCode : 02 ValueCode : 3411-11 | XML |