XML parsing with nodes

phoenix516
Tera Contributor

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.

4 REPLIES 4

ChrisBurks
Mega Sage

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]);


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.


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);


              }


      }


}


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):