Edit KML with XSLT

1,132 views
Skip to first unread message

lrochele

unread,
Mar 13, 2007, 10:57:45 AM3/13/07
to KML Discussions
Hello everyone,

do you know if it is possible to open and edit a KML file using an XSLT ? In fact, I want to add some tags (<Region> for instance) at certain particular locations in the KML, and I need to do it automatically, so I don't have to do it for the 1000 KML files that I have. Does anyone know something about that ?

thank you

Louis

ManoM

unread,
Mar 13, 2007, 1:00:20 PM3/13/07
to KML Discussions
Hi Louis,

Sure, it's not a problem at all. KML files are XML files, so there's no real issue with using XSLT on KML. XSLT 2.0 offers some nice features, like for-each-group which allows you to do easy grouping and sorting of Placemarks. If you're trying to insert a region into a Placemark, that's pretty easy:

Code:

<xsl:template match="kml:Placemark">
<Placemark>
<xsl:apply-templates select="kml:name" />
<xsl:apply-templates select="kml:styleUrl" />
<xsl:apply-templates select="kml:Polygon" />
<Region>
<LatLonAltBox>
<north>50.625</north>
<south>45</south>
<east>28.125</east>
<west>22.5</west>
<minAltitude>10</minAltitude>
<maxAltitude>50</maxAltitude>
</LatLonAltBox>
<Lod>
<minLodPixels>128</minLodPixels>
<maxLodPixels>1024</maxLodPixels>
<minFadeExtent>128</minFadeExtent>
<maxFadeExtent>128</maxFadeExtent>
</Lod>
</Region>
</Placemark>
</xsl:template>



Assuming you've already created a template for name and styleUrl.

ManoM

Valery35

unread,
Mar 13, 2007, 3:50:39 PM3/13/07
to KML Discussions
To you wanted one Region to all placemarks?
If need region by center of placemark then best solution it is calculated values (spreadsheets, SQL server fields...)

Values best store in XML and tags in XSL

My old XSL:
http://editgrid.com/user/valery35/Pathv3

And xsl to XML:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns="http://earth.google.com/kml/2.1" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- An xsl template for displaying data as KML file.

Copyright (c) 2006, Valery Hronusov aka Valery35 (xbbster(at)gmail.com) . All rights reserved.

Revision History: Created 02.09.2006

-->
<xsl:output method="xml" />
<xsl:template match="/">
<kml>
<Document>
<Snippet maxLines="0"></Snippet>
<name>
Path calculator
</name>
<StyleMap id="default">
<Pair>
<key>normal</key>
<styleUrl>flatfile://kh.google.com:80/styles/#15899:Class 3 - initial (site) (normal)</styleUrl>
</Pair>
<Pair>
<key>highlight</key>
<styleUrl>flatfile://kh.google.com:80/styles/#15899:Class 3 - initial (site) (highlight)</styleUrl>
</Pair>
</StyleMap>
<Style id="15899:Class 3 - initial (site) (highlight)">
<IconStyle>
<Icon>
<href>http://kh.google.com:80/flatfile?lf-0-icons/airports_new_nh.png</href>
<y>32</y>
<w>32</w>
<h>32</h>
</Icon>
</IconStyle>
<LabelStyle></LabelStyle>
<LineStyle>
<antialias>0</antialias>
</LineStyle>
<PolyStyle>
<fill>0</fill>
<outline>0</outline>
</PolyStyle>
</Style>
<Style id="15899:Class 3 - initial (site) (normal)">
<IconStyle>
<scale>0.9</scale>
<Icon>
<href>http://kh.google.com:80/flatfile?lf-0-icons/airports_new_nh.png</href>
<w>32</w>
<h>32</h>
</Icon>
</IconStyle>
<LabelStyle>
<scale>0</scale>
</LabelStyle>
<LineStyle>
<antialias>0</antialias>
</LineStyle>
<PolyStyle>
<fill>0</fill>
<outline>0</outline>
</PolyStyle>
</Style>
<xsl:apply-templates />
</Document>
</kml>
</xsl:template>
<xsl:template match="sheet">
<!-- Points -->
<Folder>
<Snippet maxLines="0"></Snippet>
<name>Points</name>
<xsl:for-each select="row[@row >= 2]">
<Placemark>
<Snippet maxLines="0"></Snippet>
<name>
<xsl:value-of select="cell[@col=0]" />
</name>
<description>
<!CDATA[to: ]]><xsl:value-of select="cell[@col=0]" /><!CDATA[
<br>seg: ]]><xsl:value-of select="format-number(cell[@col=3]/@value,'#.000')" /><!CDATA[km ]]>
<xsl:value-of select="format-number(cell[@col=3]/@value*0.621371192,'#.000')" /><!CDATA[mi
<br>sum: ]]><xsl:value-of select="format-number(cell[@col=4]/@value,'#.000')" /><!CDATA[km ]]>
<xsl:value-of select="format-number(cell[@col=4]/@value*0.621371192,'#.000')" /><!CDATA[mi
]]>
</description>
<styleUrl>#default</styleUrl>
<TimeStamp>
<when>
<xsl:value-of select="cell[@col=7]/@value" />
</when>
</TimeStamp>
<Point>
<coordinates>
<xsl:value-of select="cell[@col=2]/@value" />,
<xsl:value-of select="cell[@col=1]/@value" />
</coordinates>
</Point>
</Placemark>
</xsl:for-each>
</Folder>
<!-- /Points -->
<!-- Segments -->
<Folder>
<Snippet maxLines="0"></Snippet>
<name>Segments</name>
<xsl:for-each select="row[@row >= 3]">
<xsl:variable name="row" select="@row - 1" />
<xsl:variable name="prev" select="../row[@row = $row]" />
<Placemark>
<name>
from: <xsl:value-of select="$prev/cell[@col=0]" /> to: <xsl:value-of select="cell[@col=0]" />
</name>
<Snippet maxLines="0"></Snippet>
<description>
<!CDATA[
seg: ]]><xsl:value-of select="format-number(cell[@col=3]/@value,'#.000')" /><!CDATA[km ]]>
<xsl:value-of select="format-number(cell[@col=3]/@value*0.621371192,'#.000')" /><!CDATA[mi<br>
sum: ]]><xsl:value-of select="format-number(cell[@col=4]/@value,'#.000')" /><!CDATA[km ]]>
<xsl:value-of select="format-number(cell[@col=4]/@value*0.621371192,'#.000')" /><!CDATA[mi
]]>
</description>
<Style>
<LineStyle>
<color>7fffaaff</color>
<width>4</width>
</LineStyle>
</Style>
<TimeStamp>
<when>
<xsl:value-of select="cell[@col=7]/@value" />
</when>
</TimeStamp>
<LineString>
<tessellate>1</tessellate>
<coordinates>
<xsl:value-of select="$prev/cell[@col=2]/@value" />,<xsl:value-of select="$prev/cell[@col=1]/@value" />,0
<xsl:value-of select="cell[@col=2]/@value" />,<xsl:value-of select="cell[@col=1]/@value" />,0
</coordinates>
</LineString>
</Placemark>
</xsl:for-each>
</Folder>
<!-- Segments -->
<!-- Path-->
<Folder>
<Snippet maxLines="0"></Snippet>
<name>Path</name>
<Placemark>
<name>
Path
</name>
<Snippet maxLines="0"></Snippet>
<styleUrl>#default</styleUrl>
<LineString>
<tessellate>1</tessellate>
<coordinates>
<xsl:for-each select="row[@row >= 3]">
<xsl:variable name="row" select="@row - 1" />
<xsl:variable name="prev" select="../row[@row = $row]" />
<xsl:value-of select="$prev/cell[@col=2]/@value" />,<xsl:value-of select="$prev/cell[@col=1]/@value" />,0
<xsl:value-of select="cell[@col=2]/@value" />,<xsl:value-of select="cell[@col=1]/@value" />,0
</xsl:for-each>
</coordinates>
</LineString>
</Placemark>
</Folder>
<!-- /Path-->
</xsl:template>
</xsl:stylesheet>

Maybe it is help also.

Walt_Haas

unread,
Mar 17, 2007, 5:56:53 PM3/17/07
to KML Discussions
Here's another XSLT script that I wrote to convert a KML file to a slightly different XML schema. This runs fine using xsltproc on Fedora Core 6. Maybe you can learn something from it. -- Walt
--------
Code:

<?xml version="1.0" encoding="UTF-8"?>

<!--**
* Principal XSLT stylesheet to generate avalanches.xml
* from slidepaths.kml file supplied by State of Utah
*
* Copyright (c) Walter O. Haas 2007
* Released under the GNU Public License
* See http://opensource.org/licenses/gpl-license.php
*-->

<!-- The State of Utah supplies data in a KML 2.0 file exported
by Arc2Earth which starts with a kml element which sets
the default XML namespace. We define the kml namespace
here so we can deal with the elements in the KML file. -->
<xsl:stylesheet version="1.1"
xmlns:kml="http://earth.google.com/kml/2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:preserve-space elements="*" />
<xsl:output method="xml" encoding="UTF-8" indent="yes" />

<!-- Root node -->
<xsl:template match="/">
<xsl:comment>
***** GENERATED FILE - DO NOT EDIT ******
* Any edits to this file will be lost *
* the next time it is generated *
*****************************************</xsl:comment>
<avalanches>
<xsl:apply-templates select="//kml:Placemark"/>
</avalanches>
</xsl:template>

<!-- Each avalanche path in the KML is
described by a Placemark element -->

<xsl:template match="kml:Placemark">
  <xsl:variable name="id" select="@id" />
<xsl:variable name="lng_lat"
select="normalize-space(*/kml:Point/kml:coordinates)"/>
<xsl:variable name="lat"
select="substring-before(substring-after($lng_lat, ','), ',')"/>
<xsl:variable name="lng" select="substring-before($lng_lat,',')"/>
<xsl:variable name="date" select="concat('Placemark ',$id)"/>
<xsl:text>

</xsl:text>
<xsl:comment>From Placemark <xsl:value-of select="$id"/></xsl:comment>
<xsl:text>
</xsl:text>
<avalanche date="{$date}" lat="{$lat}" lng="{$lng}">
<xsl:text>&#xA; </xsl:text>
<description />
<xsl:text>&#xA; </xsl:text>
<path>
<xsl:text>&#xA;</xsl:text>
<xsl:apply-templates select="*/kml:Polygon//kml:coordinates" />
<xsl:text>&#xA; </xsl:text>
</path>
<xsl:text>&#xA; </xsl:text>
</avalanche>
<xsl:text>&#xA;</xsl:text>
</xsl:template>

<!-- The actual avalanche path is described by a Polygon -->
<xsl:template match="kml:Polygon//kml:coordinates">
<xsl:variable name="path">
<xsl:call-template name="make-path">
<xsl:with-param name="coord-string"
select="concat(normalize-space(.), ' ')" />
</xsl:call-template>
</xsl:variable>
<xsl:copy-of select="$path"/>
</xsl:template>

<!-- Generate coordinates from coord-string parameter -->
<xsl:template name="make-path">
<xsl:param name="coord-string" />
<xsl:variable name="lng_lat_alt"
select="substring-before($coord-string, ' ')"/>
<xsl:variable name="coord-pair"
select="substring-before($lng_lat_alt,',0')"/>
<xsl:variable name="reduced-string"
select="substring-after($coord-string, ' ')"/>
<xsl:text> </xsl:text>
<xsl:element name="coordinates">
<xsl:value-of select="$coord-pair"/>
</xsl:element>
<xsl:text>&#xA;</xsl:text>
<xsl:if test="normalize-space($reduced-string)">
<xsl:call-template name="make-path">
<xsl:with-param name="coord-string" select="$reduced-string" />
</xsl:call-template>
</xsl:if>
</xsl:template>

</xsl:stylesheet>

Reply all
Reply to author
Forward
0 new messages