private function parseResponse($xml)
 {
     try {
         $shipmentStatusXml = new \SimpleXMLElement($xml);
     } catch (\Exception $e) {
         throw Exception::createFromSimpleXMLException($e);
     }
     $packageXml = $shipmentStatusXml->xpath('//Package')[0];
     $delivered = 'true' === (string) $packageXml->Delivered;
     $events = array();
     foreach ($packageXml->xpath('./Events/Event') as $index => $eventXml) {
         $city = (string) $eventXml->City;
         $state = (string) $eventXml->State;
         $location = null;
         if (strlen($city) > 0 && strlen($state) > 0) {
             $location = sprintf('%s, %s', $city, $state);
         }
         $shipmentEventType = null;
         if ($delivered && 0 === $index) {
             // events are ordered in a descending order
             $shipmentEventType = ShipmentEvent::TYPE_DELIVERED;
         }
         $events[] = new ShipmentEvent(new \DateTime((string) $eventXml->EventTime), (string) $eventXml->Description, $location, $shipmentEventType);
     }
     return new ShipmentInformation($events, new \DateTime((string) $packageXml->Exp_Del_Date));
 }
 private function parseTrackResponse($xml, $trackingNumber)
 {
     try {
         $trackResponseXml = new \SimpleXMLElement($xml);
     } catch (\Exception $e) {
         throw Exception::createFromSimpleXMLException($e);
     }
     $trackInfoElements = $trackResponseXml->xpath(sprintf('//TrackInfo[@ID=\'%s\']', $trackingNumber));
     if (count($trackInfoElements) < 1) {
         throw new Exception('Tracking information not found in the response.');
     }
     $trackInfoXml = reset($trackInfoElements);
     $events = array();
     foreach ($trackInfoXml->xpath('./*[self::TrackDetail|self::TrackSummary]') as $trackDetailXml) {
         $city = (string) $trackDetailXml->EventCity;
         $state = (string) $trackDetailXml->EventState;
         $label = (string) $trackDetailXml->Event;
         $eventCode = (string) $trackDetailXml->EventCode;
         $location = null;
         if (strlen($city) > 0 && strlen($state) > 0) {
             $location = sprintf('%s, %s', $city, $state);
         }
         $date = new \DateTime((string) $trackDetailXml->EventDate . ' ' . (string) $trackDetailXml->EventTime);
         $shipmentEventType = null;
         if (in_array($eventCode, USPS\EventCode::getDeliveredCodes())) {
             $shipmentEventType = ShipmentEvent::TYPE_DELIVERED;
         } elseif (in_array($eventCode, USPS\EventCode::getReturnedToShipperCodes())) {
             $shipmentEventType = ShipmentEvent::TYPE_RETURNED_TO_SHIPPER;
         } elseif (in_array($eventCode, USPS\EventCode::getDeliveryAttemptCodes())) {
             $shipmentEventType = ShipmentEvent::TYPE_DELIVERY_ATTEMPTED;
         }
         $events[] = new ShipmentEvent($date, $label, $location, $shipmentEventType);
     }
     return new ShipmentInformation($events);
 }
 private function parse($xml)
 {
     try {
         $trackResponseXml = new \SimpleXMLElement($xml);
     } catch (\Exception $e) {
         throw Exception::createFromSimpleXMLException($e);
     }
     $events = array();
     foreach ($trackResponseXml->xpath('//Events/Event') as $eventXml) {
         $location = null;
         if ($eventXml->Location->count() > 0) {
             $location = (string) $eventXml->Location;
         }
         $status = (string) $eventXml->Status;
         $date = new \DateTime((string) $eventXml->DateTime);
         $shipmentEventType = null;
         if ('Item successfully delivered' === $status) {
             $shipmentEventType = ShipmentEvent::TYPE_DELIVERED;
         }
         $events[] = new ShipmentEvent($date, $status, $location, $shipmentEventType);
     }
     return new ShipmentInformation($events);
 }
 private function parse($xml)
 {
     try {
         $trackResponseXml = new \SimpleXMLElement($xml);
     } catch (\Exception $e) {
         throw Exception::createFromSimpleXMLException($e);
     }
     if ('Failure' === (string) $trackResponseXml->Response->ResponseStatusDescription) {
         if (null !== $trackResponseXml->Response->Error) {
             // No tracking information available
             throw new \Exception((string) $trackResponseXml->Response->Error->ErrorDescription);
         }
         throw new \Exception('Unknown failure');
     }
     $packageReturned = $trackResponseXml->Shipment->Package->ReturnTo->count() > 0;
     $events = array();
     foreach ($trackResponseXml->xpath('//Package/Activity') as $activityXml) {
         $city = (string) $activityXml->ActivityLocation->Address->City;
         $state = (string) $activityXml->ActivityLocation->Address->StateProvinceCode;
         $label = (string) $activityXml->Status->StatusType->Description;
         $statusCode = (string) $activityXml->Status->StatusType->Code;
         $location = null;
         if (strlen($city) > 0 && strlen($state) > 0) {
             $location = sprintf('%s, %s', $city, $state);
         }
         $date = \DateTime::createFromFormat('YmdHis', (string) $activityXml->Date . (string) $activityXml->Time);
         $shipmentEventType = null;
         if ('D' === $statusCode) {
             // delivered
             $shipmentEventType = ShipmentEvent::TYPE_DELIVERED;
         } elseif ('X' === $statusCode) {
             // exception
             if (false !== stripos($label, 'DELIVERY ATTEMPT')) {
                 $shipmentEventType = ShipmentEvent::TYPE_DELIVERY_ATTEMPTED;
             }
             if ($packageReturned && false !== stripos($label, 'RETURN')) {
                 $shipmentEventType = ShipmentEvent::TYPE_RETURNED_TO_SHIPPER;
             }
         }
         $events[] = new ShipmentEvent($date, $label, $location, $shipmentEventType);
     }
     $scheduledDeliveryDate = null;
     if ($trackResponseXml->Shipment->ScheduledDeliveryDate->count() > 0) {
         \DateTime::createFromFormat('Ymd', (string) $trackResponseXml->Shipment->ScheduledDeliveryDate);
     }
     return new ShipmentInformation($events, $scheduledDeliveryDate);
 }
 private function parseTrackReply($xml)
 {
     try {
         $trackReplyXml = new \SimpleXMLElement($xml);
     } catch (\Exception $e) {
         throw Exception::createFromSimpleXMLException($e);
     }
     $trackReplyXml->registerXPathNamespace('v9', 'http://fedex.com/ws/track/v9');
     $events = array();
     foreach ($trackReplyXml->xpath('//v9:TrackDetails/v9:Events') as $eventXml) {
         $city = (string) $eventXml->Address->City;
         $state = (string) $eventXml->Address->StateOrProvinceCode;
         $location = null;
         if (strlen($city) > 0 && strlen($state) > 0) {
             $location = sprintf('%s, %s', $city, $state);
         }
         $date = new \DateTime((string) $eventXml->Timestamp);
         $shipmentEventType = null;
         $eventXmlType = (string) $eventXml->EventType;
         if ('DL' === $eventXmlType) {
             $shipmentEventType = ShipmentEvent::TYPE_DELIVERED;
         }
         $events[] = new ShipmentEvent($date, (string) $eventXml->EventDescription, $location, $shipmentEventType);
     }
     return new ShipmentInformation($events);
 }