I am writing a REST API that simply gets a response for a url. However the challenging part is that the response is in xml format instead of json. I am not sure how to parse this xml and get specific values such as Status, Facility Description (all inside the event tag) and Ship Date. Here is what I have so far but i am pretty stuck. Thank you for the help.
Sample XML response:
<ShipmentStatus xmlns:xsi="http://www.w3.org/2001/XMLSchema- instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Packages>
<Package>
<Events>
<Event>
<Status>AA</Status>
<Description>DATA ENTRY</Description>
<EventTime>2014-03-13T10:48:05.14</EventTime>
<Facility>Commerce</Facility>
<City>COMMERCE</City>
<State>CA</State>
<Zip>90040</Zip>
</Event>
</Events>
<Tracking>C11421500000014</Tracking>
<Exp_Del_Date>2014-03-14T00:00:00</Exp_Del_Date>
<ShipDate>2014-03-13T00:00:00</ShipDate>
<Delivered>false</Delivered>
<Zip>90210</Zip>
<Service>S</Service>
<POD/>
<Error/>
</Package>
</Packages>
<Note>Results Provided by OnTrac at 3/13/2014 10:48 AM</Note>
<Error/>
</ShipmentStatus>
My attempt at REST API:
Http h = new Http();
HttpRequest req = new HttpRequest();
// url that returns the XML in the response body
TrackingNumber ='123456';
req.setEndpoint('https://www.shippingstatus.net/ShippingServices.svc/V5/shipments?tn=' + TrackingNumber);
req.setMethod('GET');
HttpResponse res = h.send(req);
Dom.Document doc = res.getBodyDocument();
//Retrieve the root element for this document.
Dom.XMLNode packages = doc.getRootElement(); //is packages the root element?
for(Dom.XMLNode child : packages.getChildElements()) {
System.debug(child.getText()); //but how do I get specific tag values like status, facility, description etc???
}
Latest Attempt:
public class TracProcess {
public class trackNumberInput {
@InvocableVariable(required=true)
public String trackingNumber;
}
public void getTrackingStatus(String trackingNumber){
Http h = new Http();
HttpRequest req = new HttpRequest();
// url that returns the XML in the response body
req.setEndpoint('https://www.somewebsiteurl.com/WebServices/V1/shipments?tn='+trackingNumber);
req.setMethod('GET');
HttpResponse res = h.send(req);
Dom.Document doc = res.getBodyDocument();
//Retrieve the root element for this document.
Dom.XMLNode root = doc.getRootElement();
//How do i call the classes that I have created in this web service?
}
public class ShipmentStatus{
Packages packages;
Note note;
Error error;
public void deserialize(Dom.XmlNode node){
// more looping
for(Dom.XmlNode child :node.getChildren()){
switch on child.getName(){
when 'Packages'{
packages = new Packages();
packages.deserialize(child);
}
when 'Note'{
note = new Note();
note.deserialize(child);
}
when 'Error'{
error = new Error();
error.deserialize(child);
}
}
}
}
}
public class Packages{
Package package; //keeps on showing error on this because it is a reserved identifier? how do i fix this?
public void deserialize(Dom.XmlNode node){
for(Dom.XmlNode child :node.getChildren()){
if(child.getName() == 'Package'){
package = new Package();
package.deserialize(child);
}
}
}
}
public class Package{
Events events;
Tracking tracking;
Exp_Del_Date expDelDate;
ShipDate sd;
Delivered delivered;
Zip zip;
Service service;
POD pod;
Error error;
public void deserialize(Dom.XmlNode node){
for(Dom.XmlNode child :node.getChildren()){
switch on child.getName(){
when 'Events'{
events = new Events();
events.deserialize(child);
}
when 'Tracking'{
tracking = new Tracking();
tracking.deserialize(child);
}
when 'Exp_Del_Date'{
expDelDate = new Exp_Del_Date();
expDelDate.deserialize(child);
}
when 'ShipDate'{
sd = new ShipDate();
expDelDate.deserialize(child);
}
when 'Delivered'{
delivered = new Delivered();
delivered.deserialize(child);
}
when 'Zip'{
zip = new Zip();
zip.deserialize(child);
}
when 'Service'{
service = new Service();
service.deserialize(child);
}
when 'POD'{
pod = new POD();
pod.deserialize(child);
}
when 'Error'{
error = new Error();
error.deserialize(child);
}
}
}
}
}
public class Events{
// When we get to items that only contain primitive values, it's time
// to just extract them directly
String Event;
String Status;
String Description; //should this be string?
DateTime EventTime;
String Facility;
String City;
String State;
String Zip;
public void deserialize(Dom.XmlNode node){
for(Dom.XmlNode child :node.getChildren()){
switch on child.getName(){
when 'Event'{
Event = (String)child.getValue();
}
when 'Status'{
Status = (String)child.getValue();
}
when 'Description'{
Description = (String)child.getValue();
}
when 'EventTime'{
EventTime = (DateTime)child.getValue();
}
when 'Facility'{
Facility = (String)child.getValue();
}
when 'City'{
City = (String)child.getValue();
}
when 'State'{
State = (String)child.getValue();
}
when 'Zip'{
Zip = (String)child.getValue();
}
}
}
}
}
}
deserialize()
and pass the parsed root element into that method.