<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:gpx="http://www.topografix.com/GPX/1/1">
<!-- $Id: gpx2gma.xsl,v 1.1 2006/10/17 19:20:32 Moritz.Ringler Exp $ -->
<!-- (c) Moritz Ringler, 2006                            -->
<!-- XSLT stylesheet that converts                       -->
<!-- GPX 1.1 to Google Maps API                          -->
<!--
 * gpx2gma.xsl
 * Copyright (C) 2006 Moritz Ringler
 * $Id: gpx2gma.xsl,v 1.1 2006/10/17 19:20:32 Moritz.Ringler Exp $
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-->

<xsl:output standalone="omit" method="text"/>

<!-- The Google Maps API key of the website where the HTML output will be published -->
<xsl:param
  name="gMapsApiKey"
  select="'ABQIAAAAHk7dVLYfawjw3STahaRfZxQdx_1iLbRScZZQc-z5x7qpoedGThTgSII2tilqI6DtBtY_KkmcMe3FDA'"
  />

<!-- The maximum number of points per track segment.
    If the actual number of points in a gpx:trkseg is larger
    then only every ith point will be included in the js output,
    where i is ceil(#points/maxpts) -->
<xsl:param
  name="maxpts"
  select="10000"
  />

<!-- The output path for the generated Google Maps Javascript.
    If jsOutput is either NUL or /dev/null then no Javascript output
    will be generated -->
<xsl:param
  name="jsOutput"
  select="'map.js'"
  />

<!-- The output path for the generated HTML.
    If htmlOutput is either NUL or /dev/null then no HTML output
    will be generated -->
<xsl:param name="htmlOutput" select="'map.html'" />

<!-- The output path for the generated CSS stylesheet.
    If csOutput is either NUL or /dev/null then no CSS output
    will be generated -->
<xsl:param name="cssOutput" select="'map.css'" />

<!-- The URL under which the HTML output can locate
     the generated Javascript -->
<xsl:param name="jsURL" select="'map.js'" />

<!-- The URL under which the HTML output can locate
     the generated CSS -->
<xsl:param name="cssURL" select="'map.css'" />

<!-- The id of the map &lt;div&gt; into which the map will be loaded -->
<xsl:param name="mapDivID" select="'map'" />

<!-- The title for the generated HTML document -->
<xsl:param name="title" select="'Google Kartenansicht'" />

<xsl:variable name="trackcolors">
    <span>"#aa0000"</span>
    <span>"#00aa00"</span>
    <span>"#0000aa"</span>
    <span>"#aaaa00"</span>
</xsl:variable>

<xsl:template match="/">
<xsl:if test="$htmlOutput ne 'NUL' and $htmlOutput ne '/dev/null'">
    <xsl:call-template name="html"/>
</xsl:if>
<xsl:if test="$cssOutput ne 'NUL' and $htmlOutput ne '/dev/null'">
    <xsl:call-template name="css"/>
</xsl:if>
<xsl:if test="$jsOutput ne 'NUL' and $htmlOutput ne '/dev/null'">
    <xsl:call-template name="js"/>
</xsl:if>
</xsl:template>

<!-- HTML output -->
<xsl:template name="html">
Creating html in <xsl:value-of select="$htmlOutput"/>
Title: <xsl:value-of select="$title"/>
Google Maps API Key: <xsl:value-of select="$gMapsApiKey"/>
Map &lt;div&gt;: <xsl:value-of select="$mapDivID"/>
Map script: <xsl:value-of select="$jsURL"/>
Map style: <xsl:value-of select="$cssURL"/>
<xsl:result-document
    href="{$htmlOutput}"
    omit-xml-declaration="yes"
    method="xhtml"
    encoding="UTF-8"
    indent="yes"
    version="1.0"
    doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
    doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN">
    <html
     xmlns="http://www.w3.org/1999/xhtml"
     xmlns:v="urn:schemas-microsoft-com:vml">
     <head>
        <meta
            name="author"
            content="Moritz Ringler" />
        <meta
            http-equiv="content-type"
            content="text/html; charset=ISO-8859-1" />
        <meta
            name="generator"
            content="Saxon XSLT Processor" />
        <meta
            http-equiv="Content-Script-Type"
            content="text/javascript" />
        <meta
            http-equiv="Content-Style-Type"
            content="text/css" />
        <meta
            name="keywords"
            content="Maps" />
        <meta
            name="page-topic"
            content="Maps" />
        <meta
            name="audience"
            content="all" />
        <meta
            name="robots"
            content="INDEX,FOLLOW" />
        <link
            rel="shortcut icon"
            href="http://mospace.de/favicon.ico" />
        <link
            rel="stylesheet"
            type="text/css"
            href="{$cssURL}" />
        <script
            type="text/javascript"><xsl:attribute
            name="src">http://maps.google.com/maps?file=api&amp;v=2&amp;key=<xsl:value-of
            select="$gMapsApiKey"/></xsl:attribute>
        </script>
        <script
            type="text/javascript"
            src="{$jsURL}" >
        </script>
        <title><xsl:value-of select="$title" /></title>
     </head>
     <body onload="loadMap()" onunload="GUnload()">
        <div style="width: 800px; height: 600px"><xsl:attribute
        name="id"><xsl:value-of select="$mapDivID"/></xsl:attribute></div>
        <div id="message"></div>
     </body>
     </html>
</xsl:result-document>
</xsl:template>

<!-- CSS output -->
<xsl:template name="css">
Creating css in <xsl:value-of select="$cssOutput"/>
<xsl:result-document
    href="{$cssOutput}"
    method="text"
    encoding="UTF-8">
v\:* {
 behavior:url(#default#VML);
}
</xsl:result-document>
</xsl:template>

<!-- JS output -->
<xsl:template name="js">
Creating Google Maps Javascript in <xsl:value-of select="$jsOutput"/>
Map &lt;div&gt;: <xsl:value-of select="$mapDivID"/>
Max. #pts. per track: <xsl:value-of select="$maxpts"/>
<xsl:result-document
    href="{$jsOutput}"
    method="text"
    encoding="UTF-8">
    <xsl:apply-templates select="gpx:gpx"/>
</xsl:result-document>
</xsl:template>

<xsl:template match="gpx:gpx">
function createUrlMarker(point, opts, url) {
  var marker = new GMarker(point, opts);
  GEvent.addListener(marker, "click", function() {
    location.href = url;
  });
  return marker;
}

function loadMap() {
    if (GBrowserIsCompatible()) {
        var map = new GMap2(document.getElementById("<xsl:value-of select="$mapDivID"/>"));
        map.addControl(new GLargeMapControl());
        map.addControl(new GMapTypeControl());
        map.addControl(new GOverviewMapControl());
        <xsl:apply-templates select="gpx:metadata/gpx:bounds" mode="center"/>
        map.setMapType(G_HYBRID_MAP);
        <xsl:apply-templates select="gpx:trk"/>
        <xsl:apply-templates select="gpx:wpt"/>
        <xsl:apply-templates select="gpx:metadata/gpx:bounds" mode="zoom"/>
    }
}
</xsl:template>

<xsl:template match="gpx:trk">
<!-- limit to maxpts per track -->
<xsl:variable name="trkstep" select="count(gpx:trkseg/gpx:trkpt) idiv $maxpts + 1"/>
    <xsl:apply-templates select="gpx:trkseg">
        <xsl:with-param name="trkstep" select="$trkstep"/>
    </xsl:apply-templates>
</xsl:template>

<xsl:template match="gpx:trkseg">
<xsl:param name="trkstep" select="1"/>
<xsl:param name="trksegidx"><xsl:number count="gpx:trkseg" level="any"/></xsl:param>
        points = [];
<xsl:apply-templates select="gpx:trkpt[(position() - 1) mod $trkstep eq 0]"/>
        map.addOverlay(new GPolyline(points,<xsl:value-of select="$trackcolors/*[$trksegidx mod 4 + 1]" />));
</xsl:template>

<xsl:template match="gpx:trkpt">
        points.push(new GLatLng(<xsl:value-of select="@lat"/>, <xsl:value-of select="@lon" />));</xsl:template>

<xsl:template match="gpx:wpt">
    <xsl:apply-templates select="gpx:name"/>
    <xsl:choose>
    <xsl:when test="exists(gpx:desc) and starts-with(normalize-space(gpx:desc/text()),'http://')">
        map.addOverlay(createUrlMarker(new GLatLng(<xsl:value-of
            select="@lat"/>, <xsl:value-of
            select="@lon"/>), {clickable: true, title: title}, "<xsl:value-of
            select="normalize-space(gpx:desc/text())"/>"));
    </xsl:when>
    <xsl:otherwise>
        map.addOverlay(new GMarker(new GLatLng(<xsl:value-of
        select="@lat"/>, <xsl:value-of
        select="@lon"/>), {clickable: false, title: title}));
    </xsl:otherwise>
    </xsl:choose>
</xsl:template>

<xsl:template match="gpx:bounds" mode="center">
        map.setCenter(new GLatLng(<xsl:value-of select="(@minlat + @maxlat) div 2"/>, <xsl:value-of select="(@minlon + @maxlon) div 2"/>), 13);
</xsl:template>

<xsl:template match="gpx:name">
        title = "<xsl:value-of select="text()"/>";</xsl:template>

<xsl:template match="gpx:bounds" mode="zoom">
        map.setZoom(
            map.getBoundsZoomLevel(
                new GLatLngBounds(
                    new GLatLng(<xsl:value-of select="@minlat"/>, <xsl:value-of select="@minlon"/>),
                    new GLatLng(<xsl:value-of select="@maxlat"/>, <xsl:value-of select="@maxlon"/>)
                )
            )
        );
</xsl:template>
</xsl:stylesheet>
