Skip to content

Instantly share code, notes, and snippets.

@lpinner
Last active August 29, 2015 14:01
Show Gist options
  • Save lpinner/5ca2b1eedf8fa5bbcdde to your computer and use it in GitHub Desktop.
Save lpinner/5ca2b1eedf8fa5bbcdde to your computer and use it in GitHub Desktop.
wms-to-kml
<?xml version="1.0" encoding="UTF-8"?>
<!--
This file is heavily modified by Luke Pinner (2014)
Originally from the ESIP-EDAC WMS to KML converter.
Which is copyright (c) 2009 Earth Data Analysis Center
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 3 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, see <http://www.gnu.org/licenses/>.
-->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns:wms="http://www.opengis.net/wms"
xmlns:math="http://exslt.org/math"
xmlns:exsl="http://exslt.org/common"
extension-element-prefixes="exsl math" >
<!-- To limit returned Folder elements -->
<xsl:param name="folder"/>
<!-- Globals -->
<xsl:variable name='version' select="/WMT_MS_Capabilities/@version"/>
<xsl:variable name='baseurlprev' select="//GetMap/DCPType/HTTP/Get/OnlineResource/@*[name()='xlink:href']"/>
<xsl:variable name='formatprev' select="//GetMap/Format"/>
<xsl:variable name='lower'>abcdefghijklmnopqrstuvwxyz</xsl:variable>
<xsl:variable name='upper'>ABCDEFGHIJKLMNOPQRSTUVWXYZ</xsl:variable>
<xsl:variable name='baseurl'>
<xsl:choose>
<xsl:when test="contains($baseurlprev,'?')">
<xsl:value-of select="$baseurlprev"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$baseurlprev"/>?
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name='format'>
<xsl:choose>
<xsl:when test="$formatprev[translate(text(),$upper,$lower)='image/png']">image/png</xsl:when>
<xsl:when test="$formatprev[translate(text(),$upper,$lower)='image/gif']">image/gif</xsl:when>
<xsl:when test="$formatprev[translate(text(),$upper,$lower)='image/jpg']">image/jpg</xsl:when>
<xsl:otherwise>image/png</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<!-- suppress default with empty template -->
<xsl:template match="text()"/>
<!-- templates -->
<xsl:template match="/">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="Capability">
<kml xmlns="http://earth.google.com/kml/2.2">
<xsl:choose>
<xsl:when test="normalize-space($folder)">
<xsl:variable name='layerpath'>
<xsl:call-template name="splitstring">
<xsl:with-param name='string' select="$folder"/>
<xsl:with-param name='search' select="'/'"/>
</xsl:call-template>
</xsl:variable>
<xsl:apply-templates>
<xsl:with-param name="layerpath" select="exsl:node-set($layerpath)/element"/>
</xsl:apply-templates>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates/>
</xsl:otherwise>
</xsl:choose>
</kml>
</xsl:template>
<!-- Match Folders (Layers w/out <Name> elements)-->
<xsl:template match="Layer[not(Name)]">
<xsl:param name="layerpath"/>
<xsl:choose>
<xsl:when test="$layerpath">
<xsl:if test="Title[text()=$layerpath[position()=1]]">
<xsl:choose>
<xsl:when test="count($layerpath)=1">
<Folder>
<name>
<xsl:value-of select="Title"/>
</name>
<Style>
<ListStyle>
<listItemType>checkOffOnly</listItemType>
<bgColor>00ffffff</bgColor>
<maxSnippetLines>2</maxSnippetLines>
</ListStyle>
</Style>
<xsl:apply-templates/>
</Folder>
</xsl:when>
<xsl:otherwise>
<!-- Apply Layer template -->
<xsl:apply-templates>
<xsl:with-param name="layerpath" select="$layerpath[position()>1]" />
</xsl:apply-templates>
</xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:when>
<xsl:otherwise>
<Folder>
<name><xsl:value-of select="Title"/></name>
<Style>
<ListStyle>
<listItemType>checkOffOnly</listItemType>
<bgColor>00ffffff</bgColor>
<maxSnippetLines>2</maxSnippetLines>
</ListStyle>
</Style>
<!-- Apply Layer template -->
<xsl:apply-templates/>
</Folder>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- Match Layers -->
<xsl:template match="Layer[Name]">
<xsl:param name="layerpath"/>
<xsl:choose>
<xsl:when test="$layerpath">
<xsl:if test="Title[text()=$layerpath[position()=1]]">
<xsl:call-template name="GroundOverlay">
<xsl:with-param name="layer" select="."/>
</xsl:call-template>
</xsl:if>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="GroundOverlay">
<xsl:with-param name="layer" select="."/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="GroundOverlay">
<xsl:param name="layer"/>
<GroundOverlay>
<!--xsl:variable name='name' select='Name'/-->
<name><xsl:value-of select="$layer/Title"/></name>
<visibility>0</visibility>
<snippet></snippet>
<Snippet maxLines="0"></Snippet>
<description>
<xsl:value-of select="$layer/Abstract"/>
<xsl:value-of select="$layer/MetadataURL/OnlineResource/@href"/>
</description>
<LookAt>
<longitude>
<xsl:value-of select="$layer/LatLonBoundingBox/@minx div 2 + $layer/LatLonBoundingBox/@maxx div 2"/>
</longitude>
<latitude>
<xsl:value-of select="$layer/LatLonBoundingBox/@miny div 2 + $layer/LatLonBoundingBox/@maxy div 2"/>
</latitude>
<range>
<xsl:value-of select="($layer/LatLonBoundingBox/@maxy - $layer/LatLonBoundingBox/@miny) * 150000"/>
</range>
<altitude>0</altitude>
<tilt>0</tilt>
<heading>0</heading>
</LookAt>
<drawOrder>2</drawOrder>
<xsl:if test="$baseurl">
<xsl:if test="$format">
<Icon>
<href>
<xsl:value-of select='$baseurl'/>VERSION=<xsl:value-of select='$version'/>&amp;REQUEST=GetMap&amp;SRS=EPSG:4326&amp;WIDTH=1024&amp;HEIGHT=1024&amp;LAYERS=<xsl:value-of select="$layer/Name"/>&amp;TRANSPARENT=TRUE&amp;FORMAT=<xsl:value-of select="$format"/>
</href>
<viewRefreshMode>onStop</viewRefreshMode>
<viewRefreshTime>0</viewRefreshTime>
<!-- LON/LAT-->
<viewFormat>BBOX=[bboxWest],[bboxSouth],[bboxEast],[bboxNorth]</viewFormat>
</Icon>
</xsl:if>
</xsl:if>
<LatLonBox>
<north>
<xsl:value-of select="$layer/LatLonBoundingBox/@maxy"/>
</north>
<south>
<xsl:value-of select="$layer/LatLonBoundingBox/@miny"/>
</south>
<east>
<xsl:value-of select="$layer/LatLonBoundingBox/@maxx"/>
</east>
<west>
<xsl:value-of select="$layer/LatLonBoundingBox/@minx"/>
</west>
</LatLonBox>
</GroundOverlay>
</xsl:template>
<!-- recursively splits string by search pattern -->
<xsl:template name="splitstring">
<xsl:param name="string"/>
<xsl:param name="search"/>
<xsl:choose>
<xsl:when test="contains($string,$search)">
<!-- first element -->
<xsl:element name="element">
<xsl:value-of select="substring-before($string,$search)"/>
</xsl:element>
<!-- recurse to next search -->
<xsl:call-template name="splitstring">
<xsl:with-param name="string" select="substring-after($string,$search)"/>
<xsl:with-param name="search" select="$search"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<!-- last element -->
<xsl:element name="element">
<xsl:value-of select="$string"/>
</xsl:element>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
<?xml version="1.0" encoding="UTF-8"?>
<!--
This file is heavily modified by Luke Pinner (2014)
Originally from the ESIP-EDAC WMS to KML converter.
Which is copyright (c) 2009 Earth Data Analysis Center
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 3 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, see <http://www.gnu.org/licenses/>.
-->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns:wms="http://www.opengis.net/wms"
xmlns:math="http://exslt.org/math"
xmlns:exsl="http://exslt.org/common"
extension-element-prefixes="exsl math" >
<!-- To limit returned Folder elements -->
<xsl:param name="folder"/>
<!-- Globals -->
<xsl:variable name='version' select="/wms:WMS_Capabilities/@version"/>
<xsl:variable name='baseurlprev' select="//wms:GetMap/wms:DCPType/wms:HTTP/wms:Get/wms:OnlineResource/@*[name()='xlink:href']"/>
<xsl:variable name='formatprev' select="//wms:GetMap/wms:Format"/>
<xsl:variable name='lower'>abcdefghijklmnopqrstuvwxyz</xsl:variable>
<xsl:variable name='upper'>ABCDEFGHIJKLMNOPQRSTUVWXYZ</xsl:variable>
<xsl:variable name='baseurl'>
<xsl:choose>
<xsl:when test="contains($baseurlprev,'?')">
<xsl:value-of select="$baseurlprev"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$baseurlprev"/>?
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name='format'>
<xsl:choose>
<xsl:when test="$formatprev[translate(text(),$upper,$lower)='image/png']">image/png</xsl:when>
<xsl:when test="$formatprev[translate(text(),$upper,$lower)='image/gif']">image/gif</xsl:when>
<xsl:when test="$formatprev[translate(text(),$upper,$lower)='image/jpg']">image/jpg</xsl:when>
<xsl:otherwise>image/png</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<!-- suppress default with empty template -->
<xsl:template match="text()"/>
<!-- templates -->
<xsl:template match="/">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="wms:Capability">
<kml xmlns="http://earth.google.com/kml/2.2">
<xsl:choose>
<xsl:when test="normalize-space($folder)">
<xsl:variable name='layerpath'>
<xsl:call-template name="splitstring">
<xsl:with-param name='string' select="$folder"/>
<xsl:with-param name='search' select="'/'"/>
</xsl:call-template>
</xsl:variable>
<xsl:apply-templates>
<xsl:with-param name="layerpath" select="exsl:node-set($layerpath)/element"/>
</xsl:apply-templates>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates/>
</xsl:otherwise>
</xsl:choose>
</kml>
</xsl:template>
<!-- Match Folders (Layers w/out <Name> elements)-->
<xsl:template match="wms:Layer[not(wms:Name)]">
<xsl:param name="layerpath"/>
<xsl:choose>
<xsl:when test="$layerpath">
<xsl:if test="wms:Title[text()=$layerpath[position()=1]]">
<xsl:choose>
<xsl:when test="count($layerpath)=1">
<Folder>
<name>
<xsl:value-of select="wms:Title"/>
</name>
<Style>
<ListStyle>
<listItemType>checkOffOnly</listItemType>
<bgColor>00ffffff</bgColor>
<maxSnippetLines>2</maxSnippetLines>
</ListStyle>
</Style>
<xsl:apply-templates/>
</Folder>
</xsl:when>
<xsl:otherwise>
<!-- Apply Layer template -->
<xsl:apply-templates>
<xsl:with-param name="layerpath" select="$layerpath[position()>1]" />
</xsl:apply-templates>
</xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:when>
<xsl:otherwise>
<Folder>
<name><xsl:value-of select="wms:Title"/></name>
<Style>
<ListStyle>
<listItemType>checkOffOnly</listItemType>
<bgColor>00ffffff</bgColor>
<maxSnippetLines>2</maxSnippetLines>
</ListStyle>
</Style>
<!-- Apply Layer template -->
<xsl:apply-templates/>
</Folder>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- Match Layers -->
<xsl:template match="wms:Layer[wms:Name]">
<xsl:param name="layerpath"/>
<xsl:choose>
<xsl:when test="$layerpath">
<xsl:if test="wms:Title[text()=$layerpath[position()=1]]">
<xsl:call-template name="GroundOverlay">
<xsl:with-param name="layer" select="."/>
</xsl:call-template>
</xsl:if>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="GroundOverlay">
<xsl:with-param name="layer" select="."/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="GroundOverlay">
<xsl:param name="layer"/>
<GroundOverlay>
<!--xsl:variable name='name' select='Name'/-->
<name><xsl:value-of select="$layer/wms:Title"/></name>
<visibility>0</visibility>
<snippet></snippet>
<Snippet maxLines="0"></Snippet>
<description>
<xsl:value-of select="$layer/wms:Abstract"/>
<xsl:value-of select="$layer/wms:MetadataURL/wms:OnlineResource/@href"/>
</description>
<LookAt>
<longitude>
<xsl:value-of select="$layer/wms:EX_GeographicBoundingBox/wms:westBoundLongitude div 2 + $layer/wms:EX_GeographicBoundingBox/wms:eastBoundLongitude div 2"/>
</longitude>
<latitude>
<xsl:value-of select="$layer/wms:EX_GeographicBoundingBox/wms:southBoundLatitude div 2 + $layer/wms:EX_GeographicBoundingBox/wms:northBoundLatitude div 2"/>
</latitude>
<range>
<xsl:value-of select="($layer/wms:EX_GeographicBoundingBox/wms:northBoundLatitude - $layer/wms:EX_GeographicBoundingBox/wms:southBoundLatitude) * 150000"/>
</range>
<altitude>0</altitude>
<tilt>0</tilt>
<heading>0</heading>
</LookAt>
<drawOrder>2</drawOrder>
<xsl:if test="$baseurl">
<xsl:if test="$format">
<Icon>
<href>
<xsl:value-of select='$baseurl'/>VERSION=<xsl:value-of select='$version'/>&amp;REQUEST=GetMap&amp;CRS=EPSG:4326&amp;WIDTH=1024&amp;HEIGHT=1024&amp;LAYERS=<xsl:value-of select="$layer/wms:Name"/>&amp;TRANSPARENT=TRUE&amp;FORMAT=<xsl:value-of select="$format"/>
</href>
<viewRefreshMode>onStop</viewRefreshMode>
<viewRefreshTime>0</viewRefreshTime>
<!-- LAT/LON-->
<viewFormat>BBOX=[bboxSouth],[bboxWest],[bboxNorth],[bboxEast]</viewFormat>
</Icon>
</xsl:if>
</xsl:if>
<LatLonBox>
<north>
<xsl:value-of select="$layer/wms:EX_GeographicBoundingBox/wms:northBoundLatitude"/>
</north>
<south>
<xsl:value-of select="$layer/wms:EX_GeographicBoundingBox/wms:southBoundLatitude"/>
</south>
<east>
<xsl:value-of select="$layer/wms:EX_GeographicBoundingBox/wms:eastBoundLongitude"/>
</east>
<west>
<xsl:value-of select="$layer/wms:EX_GeographicBoundingBox/wms:westBoundLongitude"/>
</west>
</LatLonBox>
</GroundOverlay>
</xsl:template>
<!-- recursively splits string by search pattern -->
<xsl:template name="splitstring">
<xsl:param name="string"/>
<xsl:param name="search"/>
<xsl:choose>
<xsl:when test="contains($string,$search)">
<!-- first element -->
<xsl:element name="element">
<xsl:value-of select="substring-before($string,$search)"/>
</xsl:element>
<!-- recurse to next search -->
<xsl:call-template name="splitstring">
<xsl:with-param name="string" select="substring-after($string,$search)"/>
<xsl:with-param name="search" select="$search"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<!-- last element -->
<xsl:element name="element">
<xsl:value-of select="$string"/>
</xsl:element>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment