Skip to content

Instantly share code, notes, and snippets.

@dieseltravis
Created July 9, 2010 21:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dieseltravis/470079 to your computer and use it in GitHub Desktop.
Save dieseltravis/470079 to your computer and use it in GitHub Desktop.
NYS DEC KMZ-to-KML-to-CSV for GPS POIs
<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet version="1.0" exclude-result-prefixes="xsl kml"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.opengis.net/kml/2.2"
xmlns:gx="http://www.google.com/kml/ext/2.2"
xmlns:kml="http://www.opengis.net/kml/2.2"
xmlns:atom="http://www.w3.org/2005/Atom">
<xsl:output method="text" omit-xml-declaration="yes" indent="no" />
<xsl:template match="/ | @* | * | comment() | processing-instruction() | text()">
<xsl:apply-templates select="//kml:Placemark"></xsl:apply-templates>
</xsl:template>
<!-- /kml/Document/Folder/Placemark -->
<xsl:template match="kml:Placemark">
<!-- Longitude: -->
<xsl:value-of select="substring-before(.//kml:Point/kml:coordinates, ',')"/>
<xsl:text>,</xsl:text>
<!-- Latitude: -->
<xsl:value-of select="substring-before(substring-after(.//kml:Point/kml:coordinates, ','), ',')"/>
<xsl:text>,</xsl:text>
<!-- Name: -->
<xsl:text>"</xsl:text>
<xsl:variable name="escapedName">
<xsl:call-template name="quote">
<xsl:with-param name="text" select="string(./kml:name)"/>
</xsl:call-template>
</xsl:variable>
<xsl:value-of select="string($escapedName)"/>
<xsl:text>"</xsl:text>
<xsl:text>,</xsl:text>
<!-- Only get attributes that matter -->
<xsl:text>"</xsl:text>
<xsl:for-each select ="./kml:ExtendedData/kml:SchemaData/kml:SimpleData[(@name = 'PrimtveSet' or @name = 'TentSite_s' or @name = 'Leanto' or @name = 'PicncTbl_s' or @name = 'Privy' or @name = 'Trail_s' or @name = 'Equestr' or @name = 'ScenicOvlk' or @name = 'InterpMtrl' or @name = 'WLViewPlat' or @name = 'HuntgBlind' or @name = 'FshPierETC' or @name = 'BoatLaunch' or @name = 'LoadngDock' or @name = 'HandLaunch' or @name = 'Beach' or @name = 'FlshToilet' or @name = 'Shower' or @name = 'URL') and (string(self::node()) != ' ' and string(self::node()) != '')]">
<xsl:variable name="escapedDescription">
<xsl:call-template name="quote">
<xsl:with-param name="text" select="string(.)"/>
</xsl:call-template>
</xsl:variable>
<xsl:value-of select="string($escapedDescription)"/>
<xsl:if test="position() != last()">
<xsl:text>, </xsl:text>
</xsl:if>
</xsl:for-each>
<xsl:text>"</xsl:text>
<!-- Carriage Return -->
<xsl:text>&#xa;</xsl:text>
</xsl:template>
<!-- quotes are escaped by doubling them -->
<xsl:template name="quote">
<xsl:param name="text" />
<xsl:choose>
<xsl:when test="contains($text, '&#34;')">
<xsl:value-of select="substring-before($text, '&#34;')"/>
<xsl:text>""</xsl:text>
<xsl:call-template name="quote">
<xsl:with-param name="text" select="substring-after($text,
'&#34;')"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$text"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet version="1.0" exclude-result-prefixes="xsl kml"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.opengis.net/kml/2.2"
xmlns:gx="http://www.google.com/kml/ext/2.2"
xmlns:kml="http://www.opengis.net/kml/2.2"
xmlns:atom="http://www.w3.org/2005/Atom">
<xsl:output method="text" omit-xml-declaration="yes" indent="no" />
<xsl:template match="/ | @* | * | comment() | processing-instruction() | text()">
<xsl:apply-templates select="//kml:Placemark"></xsl:apply-templates>
</xsl:template>
<!-- /kml/Document/Folder/Placemark -->
<xsl:template match="kml:Placemark">
<!-- Longitude: -->
<xsl:value-of select="substring-before(.//kml:Point/kml:coordinates, ',')"/>
<xsl:text>,</xsl:text>
<!-- Latitude: -->
<xsl:value-of select="substring-before(substring-after(.//kml:Point/kml:coordinates, ','), ',')"/>
<xsl:text>,</xsl:text>
<!-- Name: -->
<xsl:text>"</xsl:text>
<xsl:variable name="escapedName">
<xsl:call-template name="quote">
<xsl:with-param name="text" select="string(./kml:name)"/>
</xsl:call-template>
</xsl:variable>
<xsl:value-of select="string($escapedName)"/>
<xsl:text>"</xsl:text>
<xsl:text>,</xsl:text>
<!-- Only get attributes that matter -->
<xsl:text>"</xsl:text>
<xsl:for-each select ="./kml:ExtendedData/kml:SchemaData/kml:SimpleData[(@name = 'FOOT' or @name = 'HORSE' or @name = 'BIKE' or @name = 'XC' or @name = 'MOTORV' or @name = 'SNOWMB' or @name = 'ACCESSIBLE' or @name = 'MAPPWD' or @name = 'FAC_URL') and (string(self::node()) != ' ' and string(self::node()) != '')]">
<xsl:variable name="escapedDescription">
<xsl:call-template name="quote">
<xsl:with-param name="text" select="string(.)"/>
</xsl:call-template>
</xsl:variable>
<xsl:value-of select="string($escapedDescription)"/>
<xsl:if test="position() != last()">
<xsl:text>, </xsl:text>
</xsl:if>
</xsl:for-each>
<xsl:text>"</xsl:text>
<!-- Carriage Return -->
<xsl:text>&#xa;</xsl:text>
</xsl:template>
<!-- quotes are escaped by doubling them -->
<xsl:template name="quote">
<xsl:param name="text" />
<xsl:choose>
<xsl:when test="contains($text, '&#34;')">
<xsl:value-of select="substring-before($text, '&#34;')"/>
<xsl:text>""</xsl:text>
<xsl:call-template name="quote">
<xsl:with-param name="text" select="substring-after($text,
'&#34;')"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$text"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet version="1.0" exclude-result-prefixes="xsl kml"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.opengis.net/kml/2.2"
xmlns:gx="http://www.google.com/kml/ext/2.2"
xmlns:kml="http://www.opengis.net/kml/2.2"
xmlns:atom="http://www.w3.org/2005/Atom">
<xsl:output method="text" omit-xml-declaration="yes" indent="no" />
<xsl:template match="/ | @* | * | comment() | processing-instruction() | text()">
<xsl:apply-templates select="//kml:Placemark"></xsl:apply-templates>
</xsl:template>
<!-- /kml/Document/Folder/Placemark -->
<xsl:template match="kml:Placemark">
<!-- Longitude: -->
<xsl:value-of select="substring-before(.//kml:Point/kml:coordinates, ',')"/>
<xsl:text>,</xsl:text>
<!-- Latitude: -->
<xsl:value-of select="substring-before(substring-after(.//kml:Point/kml:coordinates, ','), ',')"/>
<xsl:text>,</xsl:text>
<!-- Name: -->
<xsl:text>"</xsl:text>
<xsl:variable name="escapedName">
<xsl:call-template name="quote">
<xsl:with-param name="text" select="string(./kml:name)"/>
</xsl:call-template>
</xsl:variable>
<xsl:value-of select="string($escapedName)"/>
<xsl:text>"</xsl:text>
<xsl:text>,</xsl:text>
<!-- Only get attributes that matter -->
<xsl:text>"</xsl:text>
<!-- (@name = 'WATERBODY' or @name = 'Sanitary_F' or @name = 'CAR' or @name = 'TRAIL' or @name = 'ACCESS') and -->
<xsl:for-each select ="./kml:ExtendedData/kml:SchemaData/kml:SimpleData[string(self::node()) != ' ' and string(self::node()) != '']">
<!-- label items -->
<xsl:if test="self::node()[@name = 'Sanitary_F']">
<xsl:text>Sanitary Facilities: </xsl:text>
</xsl:if>
<xsl:if test="self::node()[@name = 'CAR']">
<xsl:text>Car Parking Spots: </xsl:text>
</xsl:if>
<xsl:if test="self::node()[@name = 'TRAIL']">
<xsl:text>Trailer Parking Spots: </xsl:text>
</xsl:if>
<xsl:variable name="escapedDescription">
<xsl:call-template name="quote">
<xsl:with-param name="text" select="string(.)"/>
</xsl:call-template>
</xsl:variable>
<xsl:value-of select="string($escapedDescription)"/>
<xsl:if test="position() != last()">
<xsl:text>, </xsl:text>
</xsl:if>
</xsl:for-each>
<xsl:text>"</xsl:text>
<!-- Carriage Return -->
<xsl:text>&#xa;</xsl:text>
</xsl:template>
<!-- quotes are escaped by doubling them -->
<xsl:template name="quote">
<xsl:param name="text" />
<xsl:choose>
<xsl:when test="contains($text, '&#34;')">
<xsl:value-of select="substring-before($text, '&#34;')"/>
<xsl:text>""</xsl:text>
<xsl:call-template name="quote">
<xsl:with-param name="text" select="substring-after($text,
'&#34;')"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$text"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet version="1.0" exclude-result-prefixes="xsl kml"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.opengis.net/kml/2.2"
xmlns:gx="http://www.google.com/kml/ext/2.2"
xmlns:kml="http://www.opengis.net/kml/2.2"
xmlns:atom="http://www.w3.org/2005/Atom">
<xsl:output method="text" omit-xml-declaration="yes" indent="no" />
<xsl:template match="/ | @* | * | comment() | processing-instruction() | text()">
<xsl:apply-templates select="//kml:Placemark[string(kml:name) != 'GET DRIVING DIRECTIONS']"></xsl:apply-templates>
</xsl:template>
<!-- /kml/Document/Folder/Placemark -->
<xsl:template match="kml:Placemark">
<!-- Longitude: -->
<xsl:value-of select="substring-before(.//kml:Point/kml:coordinates, ',')"/>
<xsl:text>,</xsl:text>
<!-- Latitude: -->
<xsl:value-of select="substring-before(substring-after(.//kml:Point/kml:coordinates, ','), ',')"/>
<xsl:text>,</xsl:text>
<!-- Name: -->
<xsl:text>"</xsl:text>
<xsl:variable name="escapedName">
<xsl:call-template name="quote">
<xsl:with-param name="text" select="string(./kml:name)"/>
</xsl:call-template>
</xsl:variable>
<xsl:value-of select="string($escapedName)"/>
<xsl:text>"</xsl:text>
<xsl:text>,</xsl:text>
<!-- Only get attributes that matter -->
<xsl:text>"</xsl:text>
<xsl:for-each select ="./kml:ExtendedData/kml:SchemaData/kml:SimpleData[(@name = 'KMLURL') and (string(self::node()) != ' ' and string(self::node()) != '')]">
<!-- label items -->
<xsl:if test="self::node()[@name = 'Sanitary_F']">
<xsl:text>Sanitary Facilities: </xsl:text>
</xsl:if>
<xsl:if test="self::node()[@name = 'CAR']">
<xsl:text>Car Parking Spots: </xsl:text>
</xsl:if>
<xsl:if test="self::node()[@name = 'TRAIL']">
<xsl:text>Trailer Parking Spots: </xsl:text>
</xsl:if>
<xsl:variable name="escapedDescription">
<xsl:call-template name="quote">
<xsl:with-param name="text" select="string(.)"/>
</xsl:call-template>
</xsl:variable>
<xsl:value-of select="string($escapedDescription)"/>
<xsl:if test="position() != last()">
<xsl:text>, </xsl:text>
</xsl:if>
</xsl:for-each>
<xsl:text>"</xsl:text>
<!-- Carriage Return -->
<xsl:text>&#xa;</xsl:text>
</xsl:template>
<!-- quotes are escaped by doubling them -->
<xsl:template name="quote">
<xsl:param name="text" />
<xsl:choose>
<xsl:when test="contains($text, '&#34;')">
<xsl:value-of select="substring-before($text, '&#34;')"/>
<xsl:text>""</xsl:text>
<xsl:call-template name="quote">
<xsl:with-param name="text" select="substring-after($text,
'&#34;')"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$text"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
using System;
using System.IO;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.Caching;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Xml;
using System.Xml.Xsl;
// http://dotnetzip.codeplex.com/
// ~/bin/Ionic.Zip.dll
using Ionic.Zip;
namespace NysDecGps
{
public partial class _Default : System.Web.UI.Page
{
private const string KMLPATH = "~/App_Data/KML/";
private const string KMZPATH = "~/App_Data/KMZ/";
private const string XSLPATH = "~/App_Data/XSL/";
private const string CSVPATH = "~/CSV/";
private const string XMLSOURCES = "~/App_Data/sources.xml";
private static readonly XmlDocument xmlSources = GetXml(XMLSOURCES);
protected global::System.Web.UI.HtmlControls.HtmlForm aspnetForm;
protected global::System.Web.UI.WebControls.DropDownList KmlSources;
protected global::System.Web.UI.WebControls.Button UpdateKml;
protected global::System.Web.UI.WebControls.Button GetCsv;
protected global::System.Web.UI.WebControls.Repeater SourceTabularData;
protected void Page_Load(object sender, EventArgs e)
{
UpdateKml.Click += new EventHandler(UpdateKml_Click);
GetCsv.Click += new EventHandler(GetCsv_Click);
SourceTabularData.ItemDataBound += new RepeaterItemEventHandler(SourceTabularData_ItemDataBound);
Page.PreRender += new EventHandler(Page_PreRender);
if (!IsPostBack)
{
// data bind dropdown
foreach (XmlNode source in xmlSources.SelectNodes("/sources/source"))
{
KmlSources.Items.Add(new ListItem(source.SelectSingleNode("./title").InnerXml, source.SelectSingleNode("./shortname").InnerXml));
}
}
}
void Page_PreRender(object sender, EventArgs e)
{
// data bind table last
SourceTabularData.DataSource = xmlSources.SelectNodes("/sources/source/shortname");
SourceTabularData.DataBind();
}
void SourceTabularData_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.AlternatingItem || e.Item.ItemType == ListItemType.Item)
{
string shortName = ((XmlNode)e.Item.DataItem).InnerXml;
HtmlTableCell SourceTitle = (HtmlTableCell)e.Item.FindControl("SourceTitle");
HtmlTableCell SourceKmzLength = (HtmlTableCell)e.Item.FindControl("SourceKmzLength");
HtmlTableCell SourceKmlLength = (HtmlTableCell)e.Item.FindControl("SourceKmlLength");
HtmlTableCell SourceXslLength = (HtmlTableCell)e.Item.FindControl("SourceXslLength");
HtmlTableCell SourceCsvLength = (HtmlTableCell)e.Item.FindControl("SourceCsvLength");
HtmlTableCell SourceCsvLink = (HtmlTableCell)e.Item.FindControl("SourceCsvLink");
SourceTitle.InnerText = xmlSources.SelectSingleNode("/sources/source[shortname='" + shortName + "']/title").InnerXml;
SourceKmzLength.InnerText = GetFileSize(KMZPATH + shortName + ".kmz");
SourceKmlLength.InnerText = GetFileSize(KMLPATH + shortName + ".kml");
SourceXslLength.InnerText = GetFileSize(XSLPATH + shortName + ".xsl");
SourceCsvLength.InnerText = GetFileSize(GetCsvName(shortName));
string csvTitle = CleanFileName(xmlSources.SelectSingleNode("/sources/source[shortname='" + shortName + "']/title").InnerXml);
SourceCsvLink.InnerHtml = "<a href=\"" + this.ResolveUrl(GetCsvName(shortName)) + "\">" + csvTitle + ".csv</a>";
}
}
void UpdateKml_Click(object sender, EventArgs e)
{
string shortName = KmlSources.SelectedValue;
// download latest KMZ, unzip its KML, transform it to CSV
UpdateKmz(shortName);
UnzipKmz(shortName);
WriteCsv(shortName);
}
void GetCsv_Click(object sender, EventArgs e)
{
// generate CSV and redirect to it
string shortName = KmlSources.SelectedValue;
string csvFilePath = GetCsvName(shortName);
WriteCsv(shortName);
Response.Redirect(csvFilePath, true);
}
public static XslCompiledTransform GetXsl(string xslPath)
{
XslCompiledTransform xsl;
if (HttpContext.Current.Cache[xslPath] == null)
{
string cacheFilePath = HttpContext.Current.Server.MapPath(xslPath);
xsl = new XslCompiledTransform();
xsl.Load(cacheFilePath);
HttpContext.Current.Cache.Insert(xslPath, xsl, new CacheDependency(cacheFilePath));
}
else
{
xsl = (XslCompiledTransform)HttpContext.Current.Cache[xslPath];
}
return xsl;
}
public static XmlDocument GetXml(string xmlPath)
{
XmlDocument xmlDoc;
if (HttpContext.Current.Cache[xmlPath] == null)
{
string cacheFilePath = HttpContext.Current.Server.MapPath(xmlPath);
xmlDoc = new XmlDocument();
xmlDoc.Load(cacheFilePath);
HttpContext.Current.Cache.Insert(xmlPath, xmlDoc, new CacheDependency(cacheFilePath));
}
else
{
xmlDoc = (XmlDocument)HttpContext.Current.Cache[xmlPath];
}
return xmlDoc;
}
public static string DoXslTransform(string shortName)
{
string kmlFilePath = KMLPATH + shortName + ".kml";
string xslFilePath = XSLPATH + shortName + ".xsl";
XslCompiledTransform xsl = GetXsl(xslFilePath);
XmlDocument xDoc = GetXml(kmlFilePath);
XmlNodeReader xReader = new XmlNodeReader(xDoc);
StringBuilder xWriter = new StringBuilder();
XmlWriterSettings settings = xsl.OutputSettings.Clone();
//settings.CheckCharacters = false;
settings.ConformanceLevel = ConformanceLevel.Fragment;
settings.Indent = false;
settings.NewLineOnAttributes = false;
settings.OmitXmlDeclaration = true;
//settings.OutputMethod = XmlOutputMethod.Text;
xsl.Transform(xReader, XmlWriter.Create(xWriter, settings));
return xWriter.ToString();
}
// disallow non-word characters and multiple underscores for now
private static readonly Regex invalidChars = new Regex("\\W|__+", RegexOptions.Compiled | RegexOptions.CultureInvariant);
public static string CleanFileName(string fileName)
{
return invalidChars.Replace(fileName, "_");;
}
public static string GetCsvName(string shortName)
{
string csvFilePath = CSVPATH;
csvFilePath += CleanFileName(xmlSources.SelectSingleNode("/sources/source[shortname='" + shortName + "']/title").InnerXml);
csvFilePath += ".csv";
return csvFilePath;
}
public static void WriteCsv(string shortName)
{
string csvFilePath = GetCsvName(shortName);
string csvContent = DoXslTransform(shortName);
File.WriteAllText(HttpContext.Current.Server.MapPath(csvFilePath), csvContent);
}
public static void UpdateKmz(string shortName)
{
string url = xmlSources.SelectSingleNode("/sources/source[shortname='" + shortName + "']/url").InnerXml;
string kmzFilePath = KMZPATH + shortName + ".kmz";
// try/catch?
HttpWebRequest httpRequest = (HttpWebRequest)WebRequest.Create(url);
httpRequest.Timeout = 30000;
HttpWebResponse httpResponse = (HttpWebResponse)httpRequest.GetResponse();
if (httpResponse != null && httpResponse.StatusCode != HttpStatusCode.NotFound)
{
BinaryReader httpStreamReader = new BinaryReader(httpResponse.GetResponseStream());
byte[] buffer = new byte[httpResponse.ContentLength];
buffer = httpStreamReader.ReadBytes((int)httpResponse.ContentLength);
httpStreamReader.Close();
File.WriteAllBytes(HttpContext.Current.Server.MapPath(kmzFilePath), buffer);
}
httpResponse.Close();
}
public static void UnzipKmz(string shortName)
{
string kmzFileMappedPath = HttpContext.Current.Server.MapPath(KMZPATH + shortName + ".kmz");
string kmlFileMappedPath = HttpContext.Current.Server.MapPath(KMLPATH + shortName + ".kml");
using (ZipFile kmz = new ZipFile(kmzFileMappedPath))
{
if (File.Exists(kmlFileMappedPath))
{
File.Delete(kmlFileMappedPath);
}
kmz.ExtractSelectedEntries("*", null, HttpContext.Current.Server.MapPath(KMLPATH), ExtractExistingFileAction.OverwriteSilently);
}
}
public static string GetFileSize(string filePath)
{
filePath = HttpContext.Current.Server.MapPath(filePath);
return (File.Exists(filePath))? new FileInfo(filePath).Length.ToString() : "0";
}
}
}
<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet version="1.0" exclude-result-prefixes="xsl kml"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.opengis.net/kml/2.2"
xmlns:gx="http://www.google.com/kml/ext/2.2"
xmlns:kml="http://www.opengis.net/kml/2.2"
xmlns:atom="http://www.w3.org/2005/Atom">
<xsl:output method="text" omit-xml-declaration="yes" indent="no" />
<xsl:template match="/ | @* | * | comment() | processing-instruction() | text()">
<xsl:apply-templates select="//kml:Placemark"></xsl:apply-templates>
</xsl:template>
<!-- /kml/Document/Folder/Placemark -->
<xsl:template match="kml:Placemark">
<!-- Longitude: -->
<xsl:value-of select="substring-before(.//kml:Point/kml:coordinates, ',')"/>
<xsl:text>,</xsl:text>
<!-- Latitude: -->
<xsl:value-of select="substring-before(substring-after(.//kml:Point/kml:coordinates, ','), ',')"/>
<xsl:text>,</xsl:text>
<!-- Name: -->
<xsl:text>"</xsl:text>
<xsl:variable name="escapedName">
<xsl:call-template name="quote">
<xsl:with-param name="text" select="string(./kml:name)"/>
</xsl:call-template>
</xsl:variable>
<xsl:value-of select="string($escapedName)"/>
<xsl:text>"</xsl:text>
<xsl:text>,</xsl:text>
<!-- Only get attributes that matter -->
<xsl:text>"</xsl:text>
<xsl:for-each select ="./kml:ExtendedData/kml:SchemaData/kml:SimpleData[(@name = 'FOOT' or @name = 'HORSE' or @name = 'BIKE' or @name = 'XC' or @name = 'MOTORV' or @name = 'SNOWMB' or @name = 'ACCESSIBLE' or @name = 'MAPPWD' or @name = 'FAC_URL') and (string(self::node()) != ' ' and string(self::node()) != '')]">
<xsl:variable name="escapedDescription">
<xsl:call-template name="quote">
<xsl:with-param name="text" select="string(.)"/>
</xsl:call-template>
</xsl:variable>
<xsl:value-of select="string($escapedDescription)"/>
<xsl:if test="position() != last()">
<xsl:text>, </xsl:text>
</xsl:if>
</xsl:for-each>
<xsl:text>"</xsl:text>
<!-- Carriage Return -->
<xsl:text>&#xa;</xsl:text>
</xsl:template>
<!-- quotes are escaped by doubling them -->
<xsl:template name="quote">
<xsl:param name="text" />
<xsl:choose>
<xsl:when test="contains($text, '&#34;')">
<xsl:value-of select="substring-before($text, '&#34;')"/>
<xsl:text>""</xsl:text>
<xsl:call-template name="quote">
<xsl:with-param name="text" select="substring-after($text,
'&#34;')"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$text"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet version="1.0" exclude-result-prefixes="xsl kml"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.opengis.net/kml/2.2"
xmlns:gx="http://www.google.com/kml/ext/2.2"
xmlns:kml="http://www.opengis.net/kml/2.2"
xmlns:atom="http://www.w3.org/2005/Atom">
<xsl:output method="text" omit-xml-declaration="yes" indent="no" />
<xsl:template match="/ | @* | * | comment() | processing-instruction() | text()">
<xsl:apply-templates select="//kml:Placemark"></xsl:apply-templates>
</xsl:template>
<!-- /kml/Document/Folder/Placemark -->
<xsl:template match="kml:Placemark">
<!-- Longitude: -->
<xsl:value-of select="substring-before(.//kml:Point/kml:coordinates, ',')"/>
<xsl:text>,</xsl:text>
<!-- Latitude: -->
<xsl:value-of select="substring-before(substring-after(.//kml:Point/kml:coordinates, ','), ',')"/>
<xsl:text>,</xsl:text>
<!-- Name: -->
<xsl:text>"</xsl:text>
<xsl:variable name="escapedName">
<xsl:call-template name="quote">
<xsl:with-param name="text" select="string(./kml:name)"/>
</xsl:call-template>
</xsl:variable>
<xsl:value-of select="string($escapedName)"/>
<xsl:text>"</xsl:text>
<xsl:text>,</xsl:text>
<!-- Only get attributes that matter -->
<xsl:text>"</xsl:text>
<xsl:for-each select ="./kml:ExtendedData/kml:SchemaData/kml:SimpleData[(@name = 'Water' or @name = 'Spec_Regs' or @name = 'Stocked_sp' or @name = 'Trout_Sp' or @name = 'Map_Link') and (string(self::node()) != ' ' and string(self::node()) != '')]">
<!-- label items -->
<xsl:if test="self::node()[@name = 'Spec_Regs']">
<xsl:text>Special Regulations: </xsl:text>
</xsl:if>
<xsl:if test="self::node()[@name = 'Stocked_sp']">
<xsl:text>Stocked: </xsl:text>
</xsl:if>
<xsl:if test="self::node()[@name = 'Trout_Sp']">
<xsl:text>Trout: </xsl:text>
</xsl:if>
<xsl:if test="self::node()[@name = 'Map_Link']">
<xsl:text>Map: </xsl:text>
</xsl:if>
<xsl:variable name="escapedDescription">
<xsl:call-template name="quote">
<xsl:with-param name="text" select="string(.)"/>
</xsl:call-template>
</xsl:variable>
<xsl:value-of select="string($escapedDescription)"/>
<xsl:if test="position() != last()">
<xsl:text>, </xsl:text>
</xsl:if>
</xsl:for-each>
<xsl:text>"</xsl:text>
<!-- Carriage Return -->
<xsl:text>&#xa;</xsl:text>
</xsl:template>
<!-- quotes are escaped by doubling them -->
<xsl:template name="quote">
<xsl:param name="text" />
<xsl:choose>
<xsl:when test="contains($text, '&#34;')">
<xsl:value-of select="substring-before($text, '&#34;')"/>
<xsl:text>""</xsl:text>
<xsl:call-template name="quote">
<xsl:with-param name="text" select="substring-after($text,
'&#34;')"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$text"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
<?xml version="1.0" encoding="utf-8" ?>
<sources>
<source>
<shortname>accrec</shortname>
<title>Accessible Recreation</title>
<url>http://www.dec.ny.gov/maps/accrec.kmz</url>
</source>
<source>
<shortname>biketrails</shortname>
<title>DEC Mountain Bike Trails</title>
<url>http://www.dec.ny.gov/maps/biketrails.kmz</url>
</source>
<source>
<shortname>boatlaunch</shortname>
<title>Boat Launch Sites</title>
<url>http://www.dec.ny.gov/maps/boatlaunch.kmz</url>
</source>
<source>
<shortname>campgrounds</shortname>
<title>DEC Campgrounds</title>
<url>http://www.dec.ny.gov/maps/campgrounds.kmz</url>
</source>
<source>
<shortname>hikingtrails</shortname>
<title>DEC Hiking Trails</title>
<url>http://www.dec.ny.gov/maps/hikingtrails.kmz</url>
</source>
<source>
<shortname>pubfishing</shortname>
<title>Fishing Stream Angler Parking</title>
<url>http://www.dec.ny.gov/maps/pubfishing.kmz</url>
</source>
<source>
<shortname>xctrails</shortname>
<title>DEC Cross-Country Ski Trails</title>
<url>http://www.dec.ny.gov/maps/xctrails.kmz</url>
</source>
<!--
<source>
<shortname></shortname>
<title></title>
<url></url>
</source>
-->
</sources>
<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet version="1.0" exclude-result-prefixes="xsl kml"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.opengis.net/kml/2.2"
xmlns:gx="http://www.google.com/kml/ext/2.2"
xmlns:kml="http://www.opengis.net/kml/2.2"
xmlns:atom="http://www.w3.org/2005/Atom">
<xsl:output method="text" omit-xml-declaration="yes" indent="no" />
<xsl:template match="/ | @* | * | comment() | processing-instruction() | text()">
<xsl:apply-templates select="//kml:Placemark"></xsl:apply-templates>
</xsl:template>
<!-- /kml/Document/Folder/Placemark -->
<xsl:template match="kml:Placemark">
<!-- Longitude: -->
<xsl:value-of select="substring-before(.//kml:Point/kml:coordinates, ',')"/>
<xsl:text>,</xsl:text>
<!-- Latitude: -->
<xsl:value-of select="substring-before(substring-after(.//kml:Point/kml:coordinates, ','), ',')"/>
<xsl:text>,</xsl:text>
<!-- Name: -->
<xsl:text>"</xsl:text>
<xsl:variable name="escapedName">
<xsl:call-template name="quote">
<xsl:with-param name="text" select="string(./kml:name)"/>
</xsl:call-template>
</xsl:variable>
<xsl:value-of select="string($escapedName)"/>
<xsl:text>"</xsl:text>
<xsl:text>,</xsl:text>
<!-- Only get attributes that matter -->
<xsl:text>"</xsl:text>
<xsl:for-each select ="./kml:ExtendedData/kml:SchemaData/kml:SimpleData[(@name = 'FOOT' or @name = 'HORSE' or @name = 'BIKE' or @name = 'XC' or @name = 'MOTORV' or @name = 'SNOWMB' or @name = 'ACCESSIBLE' or @name = 'MAPPWD' or @name = 'FAC_URL') and (string(self::node()) != ' ' and string(self::node()) != '')]">
<xsl:variable name="escapedDescription">
<xsl:call-template name="quote">
<xsl:with-param name="text" select="string(.)"/>
</xsl:call-template>
</xsl:variable>
<xsl:value-of select="string($escapedDescription)"/>
<xsl:if test="position() != last()">
<xsl:text>, </xsl:text>
</xsl:if>
</xsl:for-each>
<xsl:text>"</xsl:text>
<!-- Carriage Return -->
<xsl:text>&#xa;</xsl:text>
</xsl:template>
<!-- quotes are escaped by doubling them -->
<xsl:template name="quote">
<xsl:param name="text" />
<xsl:choose>
<xsl:when test="contains($text, '&#34;')">
<xsl:value-of select="substring-before($text, '&#34;')"/>
<xsl:text>""</xsl:text>
<xsl:call-template name="quote">
<xsl:with-param name="text" select="substring-after($text,
'&#34;')"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$text"/>
</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