-
< ?php
-
/*
-
Goal:
-
* Take a GPX (which is XML) file
-
* Extract interesting records from it
-
* Calculate the arithmetic average of latitudes and longitutes
-
-
I won't tell you why exactly I needed this, just that it is part of a game
-
called geocaching
-
-
—
-
-
Class is called collector, because I am _collecting_ only the records
-
I'm interested in
-
-
Example record:
-
<wpt lat="59.4658317566" lon="24.8649997711">
-
<name>< ![CDATA[Gtehnokratt]]></name>
-
<url>< ![CDATA[http://www.geopeitus.ee/?p=350&c=2]]></url>
-
-
-
Actually there is more data, but I'm only interested in lat and lon attributes
-
and name and url elements.
-
-
Records do not have any id-s, only the url has the unique identifier at the end.
-
*/
-
-
class Collector extends FilterIterator
-
{
-
/**
-
* I only care about records with id's that are listed here
-
*/
-
private $ids = array(187, 513, 537, 542, 544, 563, 605, 715, 717, 748);
-
-
/**
-
* Set up the FilterIterator by passing our SimpleXMLIterator to it
-
*/
-
public function __construct(Iterator $it) {
-
parent::__construct($it);
-
}
-
-
/**
-
* Part of FilterIterator implementation, called for each record,
-
* responsible for the decision whether the current element is needed
-
* or not
-
*/
-
public function accept() {
-
$id = $this->get_id_from_url($this->current()->url);
-
if (in_array($id,$this->ids)) {
-
return true;
-
}
-
return false;
-
}
-
/**
-
* Extracts record ID from string
-
*/
-
private function get_id_from_url($url)
-
{
-
// http://www.geopeitus.ee/?p=350&c=514
-
preg_match('/&c=(\d+)$/',$url,$matches);
-
return $matches[1];
-
}
-
}
-
-
/*
-
SimpleXMLIterator is one of the standard SPL iterators, which makes it possible
-
to use other standard iterators when parsing XML
-
-
Second argument of simplexml_load_file is a class name and as result the XML
-
in-memory representation becomes instance of that class. Seems awkward, but
-
really useful
-
*/
-
$it = simplexml_load_file('geopeitusee.gpx','SimpleXMLIterator');
-
-
$lat_sum = $lon_sum = $count = 0.0;
-
-
// so, all the data goes in, but only the elements I'm interested in, come out
-
foreach(new Collector($it) as $element) {
-
// access subnodes with $element->name
-
// access attributes with array notation
-
printf("taking %s, lat=%f, lon = %f\n", $element->name,$element['lat'],$element['lon']);
-
-
// typecasting is needed to get correct results from SimpleXML, otherwise you would
-
// get integers
-
$lat_sum += (float)$element['lat'];
-
$lon_sum += (float)$element['lon'];
-
$count++;
-
}
-
-
// finally do the math
-
printf("Average: cnt=%d lat=%s, lon=%s\n", $count, ($lat_sum / $count), $lon_sum / $count);