diff --git a/gml.inc b/gml.inc
new file mode 100644
index 0000000..7e2f137
--- /dev/null
+++ b/gml.inc
@@ -0,0 +1,124 @@
+<?php
+// $Id: gml.inc,v 1.1.2.4 2010/05/19 14:29:42 tmcw Exp $
+
+/**
+ * @file WKT to GML converter
+ * Adapted from OpenLayers
+ */
+
+//TODO: namespace or encapsulate into a class
+
+define('NS_GML', 'http://www.opengis.net/gml');
+
+/**
+ * @param $wkt string of WKT data
+ * @return $geometry array of parsed geometry
+ *
+ * This function is not intended to be tested: 
+ * it is parsing geometries into an internal format.
+ */
+function parse_wkt($wkt) {
+  $type_string = '/^\s*(\w+)\s*\(\s*(.*)\s*\)\s*$/';
+  $paren_comma = '/\)\s*,\s*\(/';
+  $trim_parens = '/^\s*\(?(.*?)\)?\s*$/';
+
+  $geometry = array();
+  if (preg_match($type_string, $wkt, $matches)) {
+    $type = strtolower($matches[1]);
+
+    if ($type == 'polygon' ||
+        $type == 'geometrycollection' ||
+        $type == 'line') {
+      $content = $matches[2];
+      $rings = preg_split($paren_comma, $content);
+      $rings = preg_replace($trim_parens, '$1', $rings);
+
+      foreach ($rings as $ring) {
+        $r = array();
+        $points = explode(',', $ring);
+
+        foreach ($points as $point) {
+          $r[] = trim($point);
+        }
+        $geometry[] = $r;
+      }
+    }
+  }
+
+  return $geometry;
+}
+
+/**
+ * @param $geometry array of parsed geometry
+ * @return $gml string of GML XML
+ */
+function geometry_to_gml($geometry) {
+  $doc = new SimpleXMLElement(
+    "<gml:polygon xmlns:gml='http://www.opengis.net/gml'></gml:polygon>");
+  $gml = $doc->addChild('Polygon', '', NS_GML);
+  $outer = TRUE;
+
+  foreach ($geometry as $ring) {
+    if ($outer) {
+      $boundary = $gml->addChild('exterior', '', NS_GML);
+      $outer = FALSE;
+    } else {
+      $boundary = $gml->addChild('interior', '', NS_GML);
+    }
+
+    $linear_ring = $boundary->addChild('gml:LinearRing', '', NS_GML);
+    $pos = $linear_ring->addChild('gml:posList', implode(' ', $ring), NS_GML);
+    $pos->addAttribute('decimal', '.');
+  }
+
+  // this workaround required by the fact that 
+  // ->asXML() on root elements will produce XML opening and 
+  // closing tags
+  return $doc->children(NS_GML)->asXML();
+}
+
+
+/**
+ * @param $geometry array of parsed geometry
+ * @return $kml string of KML XML
+ */
+function geometry_to_multigeometry_kml($geometry) {
+  $doc = new SimpleXMLElement("<MultiGeometry></MultiGeometry>");
+  $kml = $doc->addChild('MultiGeometry');
+  foreach ($geometry as $ring) {
+    foreach ($ring as $point) {
+      // Extract coordinates from POINT element 
+      $coordinates = check_plain(str_replace(array('POINT(', ')', ' '), array('', '', ','), $point)).',0';
+      $root_point = $kml->addChild('Point');
+      $coordinates = $root_point->addChild('coordinates', $coordinates);
+    }
+  }
+  return $doc->children()->asXML();
+}
+
+/**
+ * Convert WKT to GML
+ * @param $wkt a string of wkt
+ * @return $gml a string of gml (or FALSE if no features)
+ *
+ * This is a convenience function for converting wkt to gml
+ */
+function wkt_to_gml($wkt) {
+  $geometry = parse_wkt($wkt);
+  return empty($geometry) ? FALSE : geometry_to_gml($geometry);
+}
+
+
+/**
+ * Convert WKT to GML
+ * @param $wkt a string of wkt
+ * @return $gml a string of gml (or FALSE if no features)
+ *
+ * This is a convenience function for converting wkt to MultiGeometry element collection
+ */
+function wkt_to_kml($wkt) {
+  $geometry = parse_wkt($wkt);
+  return empty($geometry) ? FALSE : geometry_to_multigeometry_kml($geometry);
+}
+
+
diff --git a/kml.module b/kml.module
index b982f00..b660dd8 100644
--- a/kml.module
+++ b/kml.module
@@ -27,6 +27,12 @@ function kml_theme() {
       'template' => 'kml-placemark',
       'path' => $path . "/views",
     ),
+    'kml_placemark_wkt' => array(
+      'arguments' => array('point' => array(), 'points' => array()),
+      'file' => 'kml_views.theme.inc',
+      'template' => 'kml-placemark-wkt',
+      'path' => $path . "/views",
+    ),
     'kml_feed_icon' => array(
       'arguments' => array(),
       'file' => 'kml_views.theme.inc',
diff --git a/views/kml-placemark-wkt.tpl.php b/views/kml-placemark-wkt.tpl.php
new file mode 100644
index 0000000..828d77f
--- /dev/null
+++ b/views/kml-placemark-wkt.tpl.php
@@ -0,0 +1,12 @@
+<Placemark>
+  <name>
+    <![CDATA[<?php print strip_tags($name) ?>]]>
+  </name>
+  <description>
+    <![CDATA[<?php print $description ?>]]>
+  </description>
+  <?php if ($styleURL): ?>
+    <styleUrl><?php echo $styleURL; ?></styleUrl>
+  <?php endif; ?>
+  <?php print $geometry ?>
+</Placemark>
diff --git a/views/kml_views.theme.inc b/views/kml_views.theme.inc
index 0ff8486..5a7c5b9 100644
--- a/views/kml_views.theme.inc
+++ b/views/kml_views.theme.inc
@@ -13,7 +13,12 @@ function template_preprocess_views_view_kml(&$vars) {
   $style = theme('kml_style', $points);
 
   foreach ($points as $point) {
-    $rows .= theme('kml_placemark', $point, $points);
+    if ($vars['options']['data_source']['provider'] == 'openlayers_wkt' && $point['wkt']) {
+      $rows .= theme('kml_placemark_wkt', $point, $points);
+    }
+    elseif ($vars['options']['data_source']['provider'] == 'lat_lon' && $point['point']) {
+      $rows .= theme('kml_placemark', $point, $points);
+    }
   }
      
   $vars['rows'] = $rows;
@@ -51,6 +56,18 @@ function template_preprocess_kml_placemark(&$vars) {
 }
 
 /**
+ * Preprocess for theme('kml_placemark_wkt').
+ */
+function template_preprocess_kml_placemark_wkt(&$vars) {
+  $vars['name'] = filter_xss_admin($vars['point']['name']);
+  $vars['description'] = filter_xss_admin($vars['point']['description']);
+  $vars['geometry'] = $vars['point']['wkt'];
+  $vars['styleURL'] = check_plain($vars['point']['styleURL']);
+
+  // @TODO: Create variable for every field that is unassigned.
+}
+
+/**
  * Theme function for feed icon.
  */
 function theme_kml_feed_icon() {
diff --git a/views/views_plugin_style_kml.inc b/views/views_plugin_style_kml.inc
index 7a10856..ed2e68a 100644
--- a/views/views_plugin_style_kml.inc
+++ b/views/views_plugin_style_kml.inc
@@ -22,6 +22,11 @@ class views_plugin_style_kml extends views_plugin_style {
   function attach_to($display_id, $path, $title) {
     $url_options = array('html' => TRUE);
 
+    $query = $this->view->get_exposed_input();
+    if ($query) {
+      $url_options['query'] = $query;
+    }
+
     // Include exposed filters
     $query = $this->view->get_exposed_input();
     if ($query) {
@@ -38,8 +43,6 @@ class views_plugin_style_kml extends views_plugin_style {
     $field_options = array(
       'name' => t('Name'),
       'description' => t('Description'),
-      'longitude' => t('Longitude'),
-      'latitude' => t('Latitude'),
     );
     
     foreach ($field_options as $k => $v) {
@@ -90,8 +93,6 @@ class views_plugin_style_kml extends views_plugin_style {
       $field_options = array(
         'name' => t('Name'),
         'description' => t('Description'),
-        'longitude' => t('Longitude'),
-        'latitude' => t('Latitude'),
       );
       $form['filename'] = array(
         '#type' => 'textfield',
@@ -104,9 +105,9 @@ class views_plugin_style_kml extends views_plugin_style {
       $form['fields'] = array(
         '#type' => 'fieldset',
         '#title' => 'Field usage',
-        '#description' => t('Select the fields that contain the latitude,
-        longitude and title of each point. Remaining fields will be available
-        as <em>$content[\'VARNAME\']</em> in <em>kml-placemark.tpl.php</em>.'),
+        '#description' => t('Select the fields that contain title of each 
+          point. Remaining fields will be available as 
+          <em>$content[\'VARNAME\']</em> in <em>kml-placemark.tpl.php</em>.'),
         '#weight' => -10,
       );
       foreach ($field_options as $k => $v) {
@@ -118,6 +119,78 @@ class views_plugin_style_kml extends views_plugin_style {
           '#required' => ($k == 'class' ? FALSE : TRUE),
         );
       }
+      $form['data_source'] = array(
+       '#type' => 'fieldset',
+       '#title' => t('Lat/Long source'),
+       '#description' => t('Select the fields that contain latitude and longitude of each point.'),
+       '#tree' => TRUE,
+       '#collapsible' => FALSE,
+      );
+      $form['data_source']['provider'] = array(
+        '#type' => 'select',
+        '#title' => t('Map Data Sources'),
+        '#description' => t('Choose which sources of data to provide latitude and langitude values.'),
+        '#options' => array(
+          'lat_lon' => t('Lat/Lon Points'),
+          'openlayers_wkt' => t('OpenLayers WKT')
+        ),
+        '#default_value' => ($this->options['data_source']['provider'] ? $this->options['data_source']['provider'] : ''),
+        '#required' => TRUE,
+      );
+      if (count($field_names > 0)) {
+        $form['data_source']['lat'] = array(
+          '#type' => 'select',
+          '#title' => t('Latitude Field'),
+          '#description' => t('Choose a field for Latitude.  This should be a field that is a decimal or float value.'),
+          '#options' => $field_names,
+          '#default_value' => $this->options['data_source']['lat'],
+          '#process' => array('views_process_dependency'),
+          '#dependency' => array('edit-style-options-data-source-provider' => array('lat_lon')),
+       //   '#required' => TRUE
+        );
+        $form['data_source']['lon'] = array(
+         '#type' => 'select',
+          '#title' => t('Longitude Field'),
+           '#description' => t('Choose a field for Longitude.  This should be a field that is a decimal or float value.'),
+          '#options' => $field_names,
+          '#default_value' => $this->options['data_source']['lon'],
+          '#process' => array('views_process_dependency'),
+          '#dependency' => array('edit-style-options-data-source-provider' => array('lat_lon')),
+        //  '#required' => TRUE
+        );
+        // Other: WKT
+        $form['data_source']['openlayers_wkt'] = array(
+          '#type' => 'select',
+          '#title' => t('WKT Field'),
+          '#description' => t('Choose the OpenLayers WKT field.'),
+          '#options' => $field_names,
+          '#default_value' => $this->options['data_source']['openlayers_wkt'],
+          '#process' => array('views_process_dependency'),
+          '#dependency' => array('edit-style-options-data-source-provider' => array('openlayers_wkt')),
+         // '#required' => TRUE
+        );
+      }
+    }
+  }
+
+  function kml_points_prerender($options, $field, &$point) {
+    static $data_source;
+    /* Select correct data source to get lat/long values */
+    if (!$data_source) {
+      $data_source = $options['provider'];
+    }
+    switch ($data_source) {
+      case 'openlayers_wkt':
+        include_once(drupal_get_path('module', 'kml').'/gml.inc');
+        $point['wkt'] = wkt_to_kml($field[$options['openlayers_wkt']]);
+      break;
+      case 'lat_lon':
+        $lat = $field[$options['lat']];
+        $lon = $field[$options['lon']];
+        $point['point'] = $lon . ',' . $lat . ',0';
+        unset($point['lat']);
+        unset($point['lon']);
+      break;
     }
   }
 
@@ -143,12 +216,6 @@ class views_plugin_style_kml extends views_plugin_style {
         elseif ($key == $this->options['fields']['description']) {
           $point['description'] = $row[$key];
         }
-        elseif ($key == $this->options['fields']['longitude']) {
-          $point['lon'] = $row[$key];
-        }
-        elseif ($key == $this->options['fields']['latitude']) {
-          $point['lat'] = $row[$key];
-        }
         else{
           $point['content'][$key] = $row[$key];
         }
@@ -158,6 +225,8 @@ class views_plugin_style_kml extends views_plugin_style {
       unset($point['lat']);
       unset($point['lon']);
 
+      /* Lat/Long pre render */
+      $this->kml_points_prerender($this->options['data_source'], $row, $point);
       if ($this->options['linestring']['enable']) {
         $points[$point['group']][] = $point;
       }
