4

Does anyone know a workable and stable program which converts csv extension files to kml?

There are many tools available online but none of them worked for me. I tried many including

  1. kmlcsv
  2. Choon-Chern Lim

I will be grateful if someone can direct me to something working.

15

There are 2 immediate options that would best get you where you are trying to go.

  1. Your first, and probably easiest option, would be to download Quantum GIS, using the OSGeo4W Installer.

    Once you have installed that program, follow this tutorial, which covers Importing a .csv file to QGIS.

    Once you have imported the file, simply right click on the layer in the table of contents, choose Save As, and save as ".kml".

    Here is a link to the QGIS User Documentation, to help you get started.

  2. Try the OGR Simple Features Library, specifically the ogr2ogr utility. This program lets you specify your input file, input file format, output file, and output file format, as well as projections and geometry columns, if necessary.

    Here is the section of documentation about reading CSV files, and creating spatially enabled layers from them: Comma Separated Value

  • 4
    I'd also go for ogr2ogr - not the easiest but probably the best solution. But you should also make sure that your data is projected correctly, or you should set the source projection with -s_srs – johanvdw Jun 6 '12 at 6:04
  • 1
    Thanks @Get Spatial. I tried the first option and it worked great. – Stat-R Jun 6 '12 at 12:39
  • @Get Spatial -- thanks for the suggestion! What I am confused about is if I have a CSV file with ~358 Columns, with each column composed of Lat,Long value, do I need to concatenate all those values into the same field? – GPP Sep 23 '16 at 2:24
3

We have developed a straightforward way to do so via a web browser - it doesn't require any downloads or plug-ins.

The only requirement is that the Latitude and Longitude should be in decimal format and should be listed as headings in that format, ie not Lat and Lon or X and Y. You can then do a batch conversion into KML.

The site is available at http://www.mapsdata.co.uk/online-file-converter/

We hope it helps you and we welcome feedback or requests for additional functionality.

1

If you're like me and are cautious about uploading sensitive data for online conversion then try this Python code.

The example on the site above will work in Python 2, and converts addresses to lat-longs and then creates a KML.

See below for my adaptation. This is designed for cases where you already have the lat-longs in a CSV. Also, allows for labeled and customized place-markers.

Step by step guide:

1) Prepare your data - with latitude and longitude in individual columns (decimal format) and include other columns that you would like to be displayed in a pop-up box when clicked. Save as CSV

2) Dowload python to suit your OS and architecture and after the install, open IDLE (python GUI) and a new window (ctrl-n). Copy-paste the code below.

3) Edit the code to suit your data and design. Places that you may want to change are identified as '#//'. Save the py script in the same folder as the CSV file (and place-marker image if desired). Run the script (f5) and you will have a working KML.

Notes: if you do want the default place-markers (yellow pins) you can delete much of the code related to the style. Also, place-mark images can be embedded when you eventually convert the KML to KMZ. This was written in Python 3.3.2.

Someone more experienced may have a better solution, but this works well for me.

import csv
import xml.dom.minidom
import sys


def GPSCoord(row):
  # combine lat-longs from their columns, returned as a string.
  return '%s,%s' % (row['longitude'],row['latitude'])

def createPlacemark(kmlDoc, row, order):
  # This creates a  element for a row of data.
  # A row is a dict.
  # Added option for place-mark label
  placemarkElement = kmlDoc.createElement('Placemark')
  nameElement = kmlDoc.createElement('name')
  placemarkElement.appendChild(nameElement)
  nameText = kmlDoc.createTextNode(row['ID'])
  # //Change 'ID' in nameText to the CSV column heading with desired labels.
  nameElement.appendChild(nameText)
  extElement = kmlDoc.createElement('ExtendedData')
  placemarkElement.appendChild(extElement)
  styleUrlElement = kmlDoc.createElement('styleUrl')
  styleUrlText = kmlDoc.createTextNode('#caseStyle')
  styleUrlElement.appendChild(styleUrlText)
  placemarkElement.appendChild(styleUrlElement)

  # Loop through the columns and create a  element for every field that has a value.
  for key in order:
    if row[key]:
      dataElement = kmlDoc.createElement('Data')
      dataElement.setAttribute('name', key)
      valueElement = kmlDoc.createElement('value')
      dataElement.appendChild(valueElement)
      valueText = kmlDoc.createTextNode(row[key])
      valueElement.appendChild(valueText)
      extElement.appendChild(dataElement)


  pointElement = kmlDoc.createElement('Point')
  placemarkElement.appendChild(pointElement)
  coordinates = GPSCoord(row)
  coorElement = kmlDoc.createElement('coordinates')
  coorElement.appendChild(kmlDoc.createTextNode(coordinates))
  pointElement.appendChild(coorElement)
  return placemarkElement


def createKML(csvReader, fileName, order):
  # This constructs the KML document from the CSV file.
  kmlDoc = xml.dom.minidom.Document()

  kmlElement = kmlDoc.createElementNS('http://earth.google.com/kml/2.2', 'kml')
  kmlElement.setAttribute('xmlns','http://earth.google.com/kml/2.2')
  kmlElement = kmlDoc.appendChild(kmlElement)
  documentElement = kmlDoc.createElement('Document')
  documentElement = kmlElement.appendChild(documentElement)

  #Setting style for normal place-markers.
  styleElement = kmlDoc.createElement('Style')
  documentElement.appendChild(styleElement)
  styleIDElement = kmlDoc.createElement('id')
  idText = kmlDoc.createTextNode('NormIconID')
  styleIDElement.appendChild(idText)
  styleElement.appendChild(styleIDElement)
  iconElement = kmlDoc.createElement('Icon')
  styleElement.appendChild(iconElement)
  hrefElement = kmlDoc.createElement('href')
  iconElement.appendChild(hrefElement)
  iconLocation = kmlDoc.createTextNode('blu-diamond.png')
  # //Change 'blu-diamond.png' to a web address or any other image in the same directory as the CSV + application. 
  #This image can be embedded when the KML is converted to KMZ (in google earth).
  hrefElement.appendChild(iconLocation)
  labelStyleElement = kmlDoc.createElement('LabelStyle')
  styleElement.appendChild(labelStyleElement)
  scaleElement = kmlDoc.createElement('scale')
  scaleText = kmlDoc.createTextNode('0.4')
  #//change label scaling to desired value 
  scaleElement.appendChild(scaleText)
  labelStyleElement.appendChild(scaleElement)

  #Setting style for place-markers when hovered over.
  styleElement = kmlDoc.createElement('Style')
  documentElement.appendChild(styleElement)
  styleIDElement = kmlDoc.createElement('id')
  idText = kmlDoc.createTextNode('HoverIconID')
  styleIDElement.appendChild(idText)
  styleElement.appendChild(styleIDElement)
  iconStyleElement = kmlDoc.createElement('IconStyle')
  iconElement = kmlDoc.createElement('Icon')
  iconStyleElement.appendChild(iconElement)
  scaleElement = kmlDoc.createElement('scale')
  scaleText = kmlDoc.createTextNode('1.2')
  #//change place-marker scaling to desired value 
  scaleElement.appendChild(scaleText)
  iconStyleElement.appendChild(scaleElement)
  styleElement.appendChild(iconStyleElement)
  hrefElement = kmlDoc.createElement('href')
  iconElement.appendChild(hrefElement)
  iconLocation = kmlDoc.createTextNode('blu-diamond.png')
  #//Change 'blu-diamond.png' to a web address or any other image in the same directory as the CSV + application. 
  #This image can be embedded when the KML is converted to KMZ (in google earth).
  hrefElement.appendChild(iconLocation)
  labelStyleElement = kmlDoc.createElement('LabelStyle')
  styleElement.appendChild(labelStyleElement)
  scaleElement = kmlDoc.createElement('scale')
  scaleText = kmlDoc.createTextNode('0.44')
  #//change label hover scaling to desired value 
  scaleElement.appendChild(scaleText)
  labelStyleElement.appendChild(scaleElement)

  #The style map
  styleMapElement = kmlDoc.createElement('StyleMap')
  documentElement.appendChild(styleMapElement)
  styleMapID = kmlDoc.createElement('id')
  styleMapIDtext = kmlDoc.createTextNode('caseStyle')
  styleMapID.appendChild(styleMapIDtext)
  styleMapElement.appendChild(styleMapID)
  pairElement = kmlDoc.createElement('Pair')
  styleMapElement.appendChild(pairElement)
  keyElement = kmlDoc.createElement('key')
  keyText = kmlDoc.createTextNode('normal')
  keyElement.appendChild(keyText)
  pairElement.appendChild(keyElement)
  styleUrl = kmlDoc.createElement('styleUrl')
  styleURLtext = kmlDoc.createTextNode('#NormIconID')
  styleUrl.appendChild(styleURLtext)
  pairElement.appendChild(styleUrl)
  pairElement = kmlDoc.createElement('Pair')
  styleMapElement.appendChild(pairElement)
  keyElement = kmlDoc.createElement('key')
  keyText = kmlDoc.createTextNode('highlight')
  keyElement.appendChild(keyText)
  pairElement.appendChild(keyElement)
  styleUrl = kmlDoc.createElement('styleUrl')
  styleURLtext = kmlDoc.createTextNode('#HoverIconID')
  styleUrl.appendChild(styleURLtext)
  pairElement.appendChild(styleUrl)

  # Skip the header line.
  csvReader.__next__()

  for row in csvReader:
    placemarkElement = createPlacemark(kmlDoc, row, order)
    documentElement.appendChild(placemarkElement)
  kmlFile = open(fileName, 'wb')
  kmlFile.write(kmlDoc.toprettyxml('  ', newl = '\n', encoding = 'utf-8'))

def main():
  # This reader opens up 'data.csv', which should be replaced with your own.
  # It creates a KML file called 'Output.kml'.

  # If an argument was passed to the script, it splits the argument on a comma
  # and uses the resulting list to specify an order for when columns get added.
  # Otherwise, it defaults to the order used in the sample.

  if len(sys.argv) >1: order = sys.argv[1].split(',')
  else: order = ['latitude','longitude','ID','Column3','column9','column5','columnN']
  #//Change to match columns in CSV. They can be in what ever order you like.
  csvreader = csv.DictReader(open('data.csv'),order)
  #//Change to your input file name. No directory needed if Python application and CSV in the same folder.
  kml = createKML(csvreader, 'Output.kml', order)
  #//Change output.kml to desired output name.
if __name__ == '__main__':
  main()
  • 2
    Issue with this: it uploads data to convert. You need to sign up for an api key and are limited to the number of checks per IP. This may have changed since you posted this (the address to check google is different), but you are still uploading data to convert. – Silas Greenback Oct 1 '15 at 18:31
1

If you use QGIS, download the plug-in named MMQGIS. There's is an option to Google Maps KML export. It is quite simple.

0

Here's a very simple perl script to split CSV to KML:

#!/usr/bin/perl

print '<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://earth.google.com/kml/2.0">
<Document>';

while (<>) {
  s/\&/\&amp;/g;  // changes & to &amp;  
  @a=split /,/;   // split the line into an array on ","

  print "<Placemark>
    <description>$a[0]</description>
    <Point><coordinates>$a[3],$a[2],0</coordinates></Point>
  </Placemark>"
};

print '</Document>
</kml>';

The above is all you need if you have a "clean" CSV - ie. no commas in the "names" and no characters that are invalid XML.

The exact sample assumes that you have a first field (field 0) that has a description, and that your latitude comes before your longitude (field 2 and 3) respectively. If it's different, just update the array fields ($a[]).

Adding support for those is trivial, however - you can use the Perl "encode" function (use HTML::Entities; at the top, and encode_entities($_); instead of the s/// line), and you can use "split /\s+/" or "split /(?<=")\s+(?=")/" if your strings are quoted.

Most programs that use KML are quite helpful and will tell you in which line the error is, don't be afraid to edit the KML file by hand if you're in a rush... You can also add a

<name>$a[1]</name> 

field inside the placemark, if you want the points to be named... :-)

To use the script, save it in a text file, say csv2kml.pl, then:

$ perl csv2kml.pl < input.csv > output.kml

If you're on Windows, without perl, you can use Tinyperl: http://tinyperl.sourceforge.net/

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.