Link to home
Start Free TrialLog in
Avatar of Richard Korts
Richard KortsFlag for United States of America

asked on

Google Maps - xml

I am trying to build a map of fixed points where the point info is in a xml file.

I found this example from Google Maps: http://code.google.com/p/gmaps-samples-v3/source/browse/trunk/xmlparsing/downloadurl.html?r=14.

This is VERY similar to what I want to do.

So I modeled my code after this. See attached. Also attached is my xml file. You can view the result at http://rkassoc.net/GVHA/Gmaps_sample_V3.htm.

Why are no points displayed?

Thanks
Gmaps-sample-V3.htm
markerssmall.xml
ASKER CERTIFIED SOLUTION
Avatar of Tom Beck
Tom Beck
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
I could not get the google example to work at all.

May I recommend a jquery ajax solution to read the xml file? No need for the util.js file include, this one all on one page. For this sample I am using the data from the google example in my markerssmall.xml as follows:
<?xml version="1.0" encoding="UTF-8"?>
<markers>
<marker lat="37.427770" lng="-122.144841"/>
<marker lat="37.413320" lng="-122.125604"/>
<marker lat="37.433480" lng="-122.139062"/>
<marker lat="37.445427" lng="-122.162307"/>
</markers>
<!doctype html>
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<meta charset="UTF-8">
<title>Untitled Document</title>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
<script type="text/javascript">  
  $(document).ready(function(){
	  var myLatlng = new google.maps.LatLng(37.4419, -122.1419);
      var myOptions = {
          zoom: 13,
          center: myLatlng,
          mapTypeId: google.maps.MapTypeId.ROADMAP
      }
      var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
	  $.ajax({
              type: "GET",
	      url: "markerssmall.xml",
	      dataType: "xml",
	      success: function(xml) {
                  $(xml).find("marker").each(function() {
		       var latlng = new google.maps.LatLng(parseFloat($(this).attr("lat")), parseFloat($(this).attr("lng")));
                        var marker = new google.maps.Marker({position: latlng, map: map});
		   });
		}
	  });
  });
</script>
</head>
<body>
  <div id="map_canvas" style="width:800px; height:600px"></div>
</body>
</html>

Open in new window

SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Another problem... A "geocode" is an ordered pair of decimal numbers separated by a comma and always in the order Lat/Lng.  In the "marker" XML it appears that the fields are reversed.

Please see http://www.laprbass.com/RAY_temp_rkorts.php where I have been able to draw a static map from the marker data by reversing the Lat/Lng information.

<?php // RAY_temp_rkorts.php
error_reporting(E_ALL);

// TEST DATA
$xml = <<<ENDXML
<markers>
<marker lat="-117.0425300" lng="33.0028040" html="13511 Orchard Gate Road" lot="1"/>
<marker lat="-117.0443730" lng="33.0043040" html="16051 Stoney Acres Road" lot="15"/>
<marker lat="-117.0449740" lng="33.0048860" html="16080 Stoney Acres Road" lot="16"/>
<marker lat="-117.0447390" lng="33.0051390" html="16076 Stoney Acres Road" lot="17"/>
<marker lat="-117.0442100" lng="33.0051210" html="16062 Stoney Acres Road" lot="18"/>
<marker lat="-117.0435160" lng="33.0051610" html="16058 Stoney Acres Road" lot="19"/>
<marker lat="-117.0366940" lng="33.0043190" html="13661 Acorn Patch Lane" lot="43"/>
<marker lat="-117.0371220" lng="33.0043280" html="13643 Acorn Patch Lane" lot="44"/>
<marker lat="-117.0375810" lng="33.0041579" html="13627 Acorn Patch Lane" lot="45"/>
<marker lat="-117.0401240" lng="33.0014850" html="15925 Lime Grove Road" lot="87"/>
<marker lat="-117.0399850" lng="33.0017890" html="15931 Lime Grove Road" lot="88"/>
<marker lat="-117.0376290" lng="33.0024200" html="15938 Overview Road" lot="105"/>
<marker lat="-117.0377460" lng="33.0020330" html="15930 Overview Road" lot="106"/>
<marker lat="-117.0360100" lng="33.0028409" html="13679 Orchard Gate Road" lot="117"/>
</markers>
ENDXML;


// THE MAPPING CLASS
// DEFINE THE GOOGLE STATIC MAPPING CLASS
class GSM
{
    // THE MAP CENTER GEOCODE, ADDRESS OR LANDMARK
    protected $center;

    // MARKER DATA ARRAY
    protected $markers;
    protected $default_icon;

    // OUR VARIABLES FOR THE MAP DISPLAY
    protected $maptype;
    protected $width;
    protected $height;
    protected $zoom;
    protected $format;

    // OUR VARIABLES FOR THE GOOGLE URL AND IMAGE TAG
    protected $alt;
    protected $title;
    protected $class;
    protected $id;
    protected $usemap;
    protected $sensor;
    protected $url;
    private $img;

    // A CONSTRUCTOR TO SET THE DEFAULT VALUES
    public function __construct()
    {
        // THE URL AND IMG TAG PARAMETERS
        $this->alt    = FALSE;
        $this->class  = FALSE;
        $this->id     = FALSE;
        $this->usemap = FALSE;
        $this->sensor = FALSE;
        $this->title  = TRUE;
        $this->url    = '';
        $this->img    = '';

        // THE CENTER AND ZOOM SCALE OF THE MAP (IF OMITTED, GOOGLE WILL CALCULATE)
        $this->center  = NULL;
        $this->zoom    = NULL;

        // THE CHARACTERISTICS OF THE MAP IMAGE
        $this->maptype = 'hybrid';    // CHOOSE
        $this->maptype = 'terrain';   // AMONG
        $this->maptype = 'satellite'; // THESE
        $this->maptype = 'roadmap';   // OPTIONS
        $this->width   = '640';
        $this->height  = '640';
        $this->format  = 'png';

        // THE DEFAULT ICON
        $this->default_icon = 'http://maps.google.com/mapfiles/ms/micons/question.png';

        // AN ARRAY OF MARKER ARRAYS
        $this->clearMarkers();

    } // END CONSTRUCTOR

    // A METHOD TO CLEAR THE MARKERS
    public function clearMarkers()
    {
        $this->markers = array();
    }

    // A SETTER TO ADD MARKERS TO THE MAP
    public function setMarker($geocode, $color='blue', $label='X')
    {
        // NOTE THAT THIS WILL WORK CORRECTLY MOST OF THE TIME
        $geocode = urlencode(urldecode($geocode));
        $this->markers[]
        = array
        ( 'color'   => $color
        , 'label'   => $label
        , 'geocode' => $geocode
        , 'icon'    => FALSE
        )
        ;
    }

    // A SETTER TO ADD ICONS TO THE MAP - VIEW SOURCE HERE: http://www.visual-case.it/cgi-bin/vc/GMapsIcons.pl
    public function setIcon($geocode, $icon=FALSE)
    {
        // NOTE THAT THIS WILL WORK CORRECTLY MOST OF THE TIME
        $geocode = urlencode(urldecode($geocode));
        if (!$icon) $icon = $this->default_icon;
        $this->markers[]
        = array
        ( 'color'   => FALSE
        , 'label'   => FALSE
        , 'geocode' => $geocode
        , 'icon'    => $icon
        )
        ;
    }

    // A SETTER TO OVERRIDE EACH OF THE DEFAULT VALUES
    public function setCenter($geocode=NULL)
    {
        // NOTE THAT THIS WILL WORK CORRECTLY MOST OF THE TIME
        $geocode = urlencode(urldecode($geocode));
        $this->center = $geocode;
    }
    public function setMaptype($x)
    {
        $this->maptype = $x;
    }
    public function setFormat($x)
    {
        $this->format = $x;
    }
    public function setWidth($x)
    {
        $this->width = $x;
    }
    public function setHeight($x)
    {
        $this->height = $x;
    }
    public function setZoom($x=NULL)
    {
        $this->zoom = $x;
    }
    public function setAlt($x=FALSE)
    {
        $this->alt = $x;
    }
    public function setTitle($x=TRUE)
    {
        $this->title = $x;
    }
    public function setClass($x=FALSE)
    {
        $this->class = $x;
    }
    public function setId($x=FALSE)
    {
        $this->id = $x;
    }
    public function setUsemap($x=FALSE)
    {
        $this->usemap = $x;
    }
    public function setSensor($x=FALSE)
    {
        $this->sensor = $x;
    }

    // A METHOD TO PREPARE AND RETRIEVE THE MAPPING URL
    public function asURL()
    {
        $s = 'false'; // SEE http://code.google.com/apis/maps/documentation/staticmaps/#Sensor
        if ($this->sensor) $s = 'true';

        // IF ICONS OR MARKERS ARE ON THE MAP, 'IMPLODE' THE DATA INTO THE URL
        $marker_string = '';
        foreach ($this->markers as $marker)
        {
            // PROCESS FOR CUSTOM ICONS
            if ($marker['icon'])
            {
                $marker_string
                = $marker_string
                . '&markers='
                . 'icon:'
                . urlencode($marker['icon'])
                . '|'
                . $marker['geocode']
                ;
                continue;
            }
            // PROCESS FOR STANDARD MARKERS
            $marker_string
            = $marker_string
            . '&markers='
            . 'color:'
            . $marker['color']
            . '|'
            . 'label:'
            . $marker['label']
            . '|'
            . $marker['geocode']
            ;
        }

        // SET CENTER AND ZOOM, IF PRESENT
        $c = '';
        if ($this->center) $c = "&center=$this->center";
        $z = '';
        if ($this->zoom)   $z = "&zoom=$this->zoom";

        // MAKE THE URL
        $this->url
        = "http://maps.google.com/maps/api/staticmap?sensor=$s"
        . $c
        . $z
        . "&size=$this->width" . 'x' . "$this->height"
        . "&format=$this->format"
        . "&maptype=$this->maptype"
        . "$marker_string"
        ;
        return $this->url;
    }

    // A METHOD TO PREPARE AND RETRIEVE THE HTML IMAGE TAG
    public function asIMG()
    {
        // GET THE URL
        if (!$this->url) $this->url = $this->asURL();

        // GET THE ALT TEXT
        $a = "$this->maptype" . ' centered ' . "$this->center";
        if ($this->alt !== FALSE) $a = $this->alt;

        // REQUIRED FIELDS
        $this->img = '<img src="' . $this->url . '" alt="' . $a . '"';

        // OPTIONAL FIELDS - PROVIDE A DEFAULT TITLE
        $t = "$this->maptype" . ' centered ' . "$this->center";
        if     ($this->title  === TRUE ) { $this->img .= ' title="' . $t .           '"'; }
        elseif ($this->title !== FALSE)  { $this->img .= ' title="' . $this->title . '"'; }

        // OPTIONAL FIELDS MAY BE OMITTED
        if ($this->class  !== FALSE) { $this->img .= ' class="'  . $this->class  . '"'; }
        if ($this->id     !== FALSE) { $this->img .= ' id="'     . $this->id     . '"'; }
        if ($this->usemap !== FALSE) { $this->img .= ' usemap="' . $this->usemap . '"'; }

        // CLOSE THE IMAGE TAG AND CLEAR THE CONSUMED URL
        $this->img .= ' />';
        $this->url = FALSE;
        return $this->img;
    }

    // A METHOD TO RETRIEVE THE IMAGE DATA (STORING DATA MAY VIOLATE GOOGLE TOS!)
    public function asData()
    {
        // GET THE URL
        if (!$this->url) $this->url = $this->asURL();

        // READ AND RETURN THE URL
        return file_get_contents($this->url);
    }

} // END CLASS

// MAKE AN OBJECT FROM THE XML STRING
$obj = simplexml_load_string($xml);

// MAKE A GOOGLE STATIC MAP OBJECT
$x = new GSM;

// ITERATE OVER THE MARKERS AND ADD THEM TO THE MAP
foreach ($obj as $marker)
{
    // NOTE THAT LATITUDE AND LONGITUDE ARE BACKWARD IN THE MARKER DATA!
    $g = $marker['lng']. ',' . $marker['lat'];
    $x->setmarker($g);
}
echo $x->asImg();

Open in new window

HTH, ~Ray
Avatar of Richard Korts

ASKER

Thanks to all, I didn't even see the util.js issue.

I know why the xml has issues, I will fix those.

After I get it working, I will award points.

Thanks
I fixed the xml (ran it through the checker at w3schools). I downloaded util.js.

Still didn't work.

Then I realized that in the xml file I had the lat/lng backwards. It is impossible to have a lat of -117. Latitude on the earth goes from 90 to - 90. So I switched those. It works!
Ray pointed out the reversed lat/lng in one of his posts. Did you try my jquery version? It's much simpler than the util.js.
Be sure to read all posts carefully, it may save you much aggravation.
Thanks for the points.
I interpreted what Ray said to mean that the lat, long pair in the Google latlng function needed to be in the order lat, lng. They were, but the data in the XML file was reversed.

No I didn't try the jquery version yet.
A geocode is always Latitude,Longitude.  These are ordered, signed decimal values, separated by a comma, trimmed and without any spaces.  Follow those guidelines and you will find a multitude of services work well with your geolocation data.  BTW, this is 1/2 of the GPS data, the other components being altitude and time.