Take the 2-minute tour ×
Geographic Information Systems Stack Exchange is a question and answer site for cartographers, geographers and GIS professionals. It's 100% free, no registration required.

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.

share|improve this question

3 Answers 3

up vote 10 down vote accepted

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

share|improve this answer
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

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.

share|improve this answer

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()
share|improve this answer
    
thanks for sharing –  Kurt Jul 28 '13 at 15:31

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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