Link to home
Start Free TrialLog in
Avatar of chrispaton
chrispaton

asked on

Create XML source from mySQL to populate Google Maps

Hi,

I am trying to populate a google map nested within my website page to display a number of different markers from an XML source which I have working.

What I want to do is create the XML source on the fly from a mySQL database without having to create the file everytime the page is called as the map will be on shown on different pages with different markers. I have tried to use XML Serialisation to create the XML but cannot find away to create and use the XML without creating the file.

Here is the xml source that is used to populate the map that I need to create;

<markers>
    <marker name="House 2" content="Blah Blah Blah" lat="47.608940" lng="-122.340141" type="house" />
    <marker name="House 2" content="Blah Blah Blah" lat="47.613590" lng="-122.344391" type="house" />
</markers>

I have the name, content, lat, lng and type fields in the database.


Thanks


Chris
Avatar of cataleptic_state
cataleptic_state
Flag of United Kingdom of Great Britain and Northern Ireland image

I'm not sure how you would do it in ASP

I use PHP to create a sitemap.
First I select the information from mySQL

$sql = "SELECT name FROM `".$config_databaseTablePrefix."products` WHERE supplier='".database_safe($_GET["supplier"])."' ORDER by search_name LIMIT 50000";

I then work on the XML structure and add in the fields from the SQL query.

      foreach($rows as $row)
      {
        print "<sitemap>";

        $sitemapHREF = "sitemap.php?supplier=".urlencode($row["supplier"]);

        print "<loc>".$sitemapBaseHREF.$sitemapHREF."</loc>";

        print "<lastmod>".date("Y-m-d",$row["imported"])."</lastmod>";

        print "</sitemap>";
      }
    }

    print "</sitemapindex>";
  }
You may want to look at it a little differently.

Instead of creating an XML file, try using a custom .NET control (free download) to populate with the results of your SQL query.

http://en.googlemaps.subgurim.net/

Using this free control, I created my own types and methods like "GoogleMap1.AddPushpin(lat,long,name,html)" inside a loop through the records in my query.

The documentation is very good with Subgurium, I suggest you take a look.

Avatar of chrispaton
chrispaton

ASKER

I have changed your suggestion into asp which is a much easier method of creating the xml source than I was trying but when I use this as the source in the javascript for the Google Maps I receive a null error
Message: 'documentElement' is null or not an object

I have copied the xml text direct from the source file that is working and added this direct to the javascript as var xmlsource to see where the error is and it also fails with the same error, the only change I have made is to the here is the line 'var xml = xmlsource.responseXML; which was var xml = data.responseXML; with data being the url of the file


                 var xmlsource = '<markers><marker name="Pan Africa Market" address="1521 1st Ave, Seattle, WA" lat="47.608940" lng="-122.340141" type="restaurant" /><marker name="Buddha Thai &amp; Bar" address="2222 2nd Ave, Seattle, WA" lat="47.613590" lng="-122.344391" type="bar" /><marker name="The Melting Pot" address="14 Mercer St, Seattle, WA" lat="47.624561" lng="-122.356445" type="restaurant" /><marker name="Ipanema Grill" address="1225 1st Ave, Seattle, WA" lat="47.606365" lng="-122.337654" type="restaurant" /><marker name="Sake House" address="2230 1st Ave, Seattle, WA" lat="47.612823" lng="-122.345673" type="bar" /><marker name="Crab Pot" address="1301 Alaskan Way, Seattle, WA" lat="47.605961" lng="-122.340363" type="restaurant" /><marker name="Mama&amp;apos;s Mexican Kitchen" address="2234 2nd Ave, Seattle, WA" lat="47.613976" lng="-122.345467" type="bar" /><marker name="Wingdome" address="1416 E Olive Way, Seattle, WA" lat="47.617214" lng="-122.326584" type="bar" /><marker name="Piroshky Piroshky" address="1908 Pike pl, Seattle, WA" lat="47.610126" lng="-122.342834" type="restaurant" /></markers>';


{
                    var xml = xmlsource.responseXML;
                    var markers = xml.documentElement.getElementsByTagName("marker");
                    for (var i = 0; i < markers.length; i++) {
                        var name = markers[i].getAttribute("name");
                        var address = markers[i].getAttribute("address");
                        var type = markers[i].getAttribute("type");
                        var point = new google.maps.LatLng(parseFloat(markers[i].getAttribute("lat")),
                                   parseFloat(markers[i].getAttribute("lng")));
                        var html = '<div id="content">' + '<div id="siteNotice">' + '</div>' + '<h3 id="firstHeading" class="firstHeading">Villa Name </h3>' + '<div id="bodyContent">' + '<img src="/images/map/villa.jpg" height="120" width="160"/><br /><b>Malaga, Costa del Sol</b><br />4 Star, Sleeps 6,' + '<p>Availability and Prices' + '</div>' + '</div>';
                        var icon = customIcons[type] || {};
                        var marker = new google.maps.Marker({ map: map, position: point, icon: icon.icon, shadow: icon.shadow });
                        bindInfoWindow(marker, map, infoWindow, html);
                    }

Open in new window

chrisrbloom - I have taken a look at this control but this only supports the v2 API and I wanted to use the latest v3.

I have tried to change the xml source string using XML DOM but still get the document Null element, the map loads ok but still no markers.
var customIcons = { villa: { icon: '/images/map/villa.gif'}  };
            function load() {
                geocoder = new google.maps.Geocoder();
                var address = ("Address");
                var map = new google.maps.Map(document.getElementById("map"),
                   {
                       center: new google.maps.LatLng(47.6145, -122.3418),
                    zoom: 12,
                    mapTypeId: 'roadmap'
                 });
                 {
                 var infoWindow = new google.maps.InfoWindow;
                 var text = '<markers><marker name="Pan Africa Market" address="1521 1st Ave, Seattle, WA" lat="47.608940" lng="-122.340141" type="restaurant" /></markers>';
                 if (window.DOMParser) {
                     parser = new DOMParser();
                     xmlDoc = parser.parseFromString(text, "text/xml");
                 }
                 else // Internet Explorer
                 {
                     xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
                     xmlDoc.async = "false";
                     xmlDoc.loadXML(text);
                 }  
                     var xml = xmlDoc.responseXML;
                     var markers = xml.documentElement.getElementsByTagName("marker");
                     for (var i = 0; i < markers.length; i++) {
                         var name = markers[i].getAttribute("name");
                         var address = markers[i].getAttribute("address");
                         var type = markers[i].getAttribute("type");
                         var point = new google.maps.LatLng(parseFloat(markers[i].getAttribute("lat")),
                                   parseFloat(markers[i].getAttribute("lng")));
                         var html = '<div id="content">' + '<div id="siteNotice">' + '</div>' + '<h3 id="firstHeading" class="firstHeading">Villa Name </h3>' + '<div id="bodyContent">' + '<img src="/images/map/villa.jpg" height="120" width="160"/><br /><b>Malaga, Costa del Sol</b><br />4 Star, Sleeps 6,' + '<p>Availability and Prices' + '</div>' + '</div>';
                         var icon = customIcons[type] || {};
                         var marker = new google.maps.Marker({ map: map, position: point, icon: icon.icon, shadow: icon.shadow });
                         bindInfoWindow(marker, map, infoWindow, html);
                     }
                 };
            }
            function bindInfoWindow(marker, map, infoWindow, html) {
                google.maps.event.addListener(marker, 'mouseover',
                              function() { infoWindow.setContent(html); infoWindow.open(map, marker); });
            }
            function downloadUrl(url, callback) {
                var request = window.ActiveXObject ?
                              new ActiveXObject('Microsoft.XMLHTTP') :
                              new XMLHttpRequest; request.onreadystatechange = function() {
                if (request.readyState == 4) { request.onreadystatechange = doNothing; callback(request, request.status); } 
            };
                                request.open('GET', url, true); request.send(null);
            }
            function doNothing() { }

Open in new window

This is PHP, so it is not really a good answer, but I can show you how I have done this using PHP and MySQL.  The page is available here:
http://www.landonbaseball.com/site_visitors.php

The CREATE TABLE statement for visitors looks like this:
$sql
= "CREATE TABLE visitors
( _key INT NOT NULL AUTO_INCREMENT
, dov  DATETIME
, lat  DECIMAL(7,3) NOT NULL DEFAULT '0.0'
, lon  DECIMAL(7,3) NOT NULL DEFAULT '0.0'
, PRIMARY KEY (_key)
, UNIQUE (lat, lon)
)"
;

<?php // landonbaseball.com/site_visitors.php

require_once('header.php');

?>

<h3>LandonBaseball.com</h3>

<p>... was recently visited by folks from these locations: </p>

<?php

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

// DRAW THE LOCAL MAP
$gsm->setWidth(620);
$gsm->setHeight(400);
$gsm->setZoom(11);

// SET A CENTER POINT
$gsm->setCenter("Landon School, Bethesda, MD");

// GET THE LAT/LON PAIRS AND SET THE MARKERS
$sql = "SELECT lat, lon FROM visitors ORDER BY dov DESC LIMIT 30";
$res = mysql_query($sql);
if (!$res) die( mysql_error() );
while ($row = mysql_fetch_assoc($res))
{
    $lat = $row["lat"];
    $lon = $row["lon"];
    // SET A MARKER ICON BY GEOCODE (LAT/LON PAIR)
	$gsm->setMarker("$lat,$lon", 'orange', 'small', NULL);
}

// SET LANDON ICON LAST (ON TOP OF OTHER MARKERS)
$gsm->setIcon("Landon School, Bethesda, MD", 'http://www.landonbaseball.com/ikons/L32.png');

// ECHO THE <img /> TAG INTO OUR HTML TO DRAW THE MAP
echo $gsm->asIMG();
echo "<br/>" . PHP_EOL;

// END OF JOB
require_once('_footer.php');
die();


// 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', $size='normal', $label='X')
    {
        $this->markers[]
        = array
        ( 'color'   => $color
        , 'label'   => $label
        , 'geocode' => $geocode
        , 'size'    => $size
        , '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)
    {
        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)
    {
        $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']
            . '|'
            . 'size:'
            . $marker['size']
            . '|'
            . $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;
    }
} // END CLASS

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of leakim971
leakim971
Flag of Guadeloupe 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
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
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
Hi leakim971,

Thanks three great solutions, I have tried all three which all work perfectly in firefox and chrome but none work in ie, the map loads but no markers appear.
Had a search and found a solution to the IE problem by adding this in,

      var xmlDoc;
      if (window.DOMParser) {
          parser = new DOMParser();
          xmlDoc = parser.parseFromString(xmlsource, "text/xml");
      }
      else // Internet Explorer
      {
          xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
          xmlDoc.async = "false";
          xmlDoc.loadXML(xmlsource);
      }

all is now working.
Thanks Leakim971, great solutions offered