CSV dosyalarını KML'ye dönüştürme

Mano Marks, Google Coğrafi API'ler Ekibi
Mart 2008

Hedef

Bu eğiticide, Python'u kullanarak Virgülle Ayrılmış Değer (CSV) verilerinden nasıl KML oluşturulacağına dair temel bilgiler sunulmaktadır. CSV verileri, günümüzde kullanılan en yaygın dosya biçimlerinden biridir. Çoğu e-tablo ve veritabanı, CSV dosyalarını hem okuyabilir hem de yazabilir. Basit biçimi bir metin düzenleyicide düzenlenebilir. Python gibi birçok programlama dilinde, CSV dosyalarını okumak ve yazmak için özel kitaplıklar bulunur. Bu nedenle, yüksek miktarda veri alışverişi için mükemmel bir ortam sunar.

Bu eğitimdeki kod örnekleri Python’da olsa da diğer programlama dillerinin çoğuna uyarlanabilir. Bu eğiticide, bir adresi boylam/enlem koordinatlarına dönüştürmek için KML'de Kullanılacak Adresler Coğrafi Kodlama'dan alınan bir kod kullanılmaktadır. Ayrıca KML 2.2'nin yeni <ExtendedData> öğesini kullanır ve Özel Veri Ekleme bölümünde açıklanan balon şablondan yararlanır. Bu nedenle, oluşturulan KML şu anda Google Haritalar'da veya diğer KML tüketen uygulamalarda desteklenmese de kod, Haritalar uyumlu KML oluşturacak şekilde uyarlanabilir.

Örnek Veriler

Bu eğiticide örnek bir CSV dosyası olarak google-addresses.csv dosyasını kullanın. Bu dosya, çeşitli ABD Google ofislerinin tüm adreslerini, telefon numaralarını ve faks numaralarını içerir. Dosya metni şöyledir:

Office,Address1,Address2,Address3,City,State,Zip,Phone,Fax
Headquarters,1600 Amphitheatre Parkway,,,Mountain View,CA,94043,650-253-0000,650-253-0001
New York Sales & Engineering Office,76 Ninth Avenue,,,New York,NY,10011,212-565-0000,212-565-0001
Ann Arbor Sales Office,201 South Division Street,,,Ann Arbor,MI,48104,734-332-6500,734-332-6501
Atlanta Sales & Engineering Office,10 10th Street NE,,,Atlanta,GA,30309,404-487-9000,404-487-9001
Boulder Sales & Engineering Office,2590 Pearl St.,,,Boulder,CO,80302,303-245-0086,303-535-5592
Cambridge Sales & Engineering Office,5 Cambridge Center,,,Cambridge,MA,02142,617-682-3635,617-249-0199
Chicago Sales & Engineering Office,20 West Kinzie St.,,,Chicago,IL,60610,312-840-4100,312-840-4101
Coppell Sales Office,701 Canyon Drive,,,Coppell,TX,75019,214-451-4000,214-451-4001
Detroit Sales Office,114 Willits Street,,,Birmingham,MI,48009,248-351-6220,248-351-6227
Irvine Sales & Engineering Office,19540 Jamboree Road,,,Irvine,CA,92612,949-794-1600,949-794-1601
Pittsburgh Engineering Office,4720 Forbes Avenue,,,Pittsburgh,PA,15213,,
Santa Monica Sales & Engineering Office,604 Arizona Avenue,,,Santa Monica,CA,90401,310-460-4000,310-309-6840
Seattle Engineering Office,720 4th Avenue,,,Kirkland,WA,98033,425-739-5600,425-739-5601
Seattle Sales Office,501 N. 34th Street,,,Seattle,WA,98103,206-876-1500,206-876-1501
Washington D.C. Public Policy Office,1001 Pennsylvania Avenue NW,,,Washington,DC,20004,202-742-6520,

Her satırın virgülle ayrılmış bir metin dizesi dizisi olduğuna dikkat edin. Her virgül bir alanı sınırlar; her satırda aynı sayıda virgül olur. İlk satır, alanların adlarını sırayla içerir. Örneğin, her satırdaki ilk metin bloğu "Office" alanı, ikinci "Adres1" vb.dir. Python bunu DictReader adlı dicts koleksiyonuna dönüştürebilir ve bu sayede her bir satıra gidebilirsiniz. Bu kod örneği, verilerinizin yapısını önceden bilmenize bağlıdır ancak alan yapısını dinamik olarak geçirmek için bazı temel işleyiciler ekleyebilirsiniz.

CSV Dosyasını Ayrıştırma

Python'un xml.dom.minidom modülü, XML belgeleri oluşturmak için harika araçlar sağlar ve KML XML olduğu için bu öğreticide oldukça yoğun bir şekilde kullanacaksınız. createElement veya createElementNS ile bir öğe oluşturup appendChild ile başka bir öğeye ekliyorsunuz. Bunlar, CSV dosyasını ayrıştırma ve KML dosyası oluşturma adımlarıdır.

  1. Modülünüze coğrafi kodlama_for_KML.py komutunu aktarın.
  2. CSV dosyaları için bir DictReader oluşturun. DictReader, dicts koleksiyonundan oluşur ve her satıra bir giriş eklenir.
  3. Python xml.dom.minidom.Document() uygulamasını kullanarak dokümanı oluşturun.
  4. createElementNS. kullanarak kök <kml> öğesini oluşturun
  5. Belgeye ekleyin.
  6. createElement kullanarak <Document> öğesi oluşturun.
  7. Değeri, appendChild öğesini kullanarak <kml> öğesine ekleyin.
  8. Her satır için bir <Placemark> öğesi oluşturun ve bu öğeyi <Document> öğesine ekleyin.
  9. Her satırdaki her sütun için bir <ExtendedData> öğesi oluşturun ve 8. adımda oluşturduğunuz <Placemark> öğesine ekleyin.
  10. Bir <Data> öğesi oluşturun ve bu öğeyi <ExtendedData> öğesine ekleyin. <Data> öğesine bir ad özelliği atayın ve setAttribute kullanarak sütun adının değerini atayın.
  11. Bir <value> öğesi oluşturun ve bu öğeyi <Data> öğesine ekleyin. Bir metin düğümü oluşturun ve createTextNode kullanarak sütunun değerini atayın. Metin düğümünü <value> öğesine ekleyin.
  12. Bir <Point> öğesi oluşturun ve bu öğeyi <Placemark> öğesine ekleyin. Bir <coordinates> öğesi oluşturun ve bu öğeyi <Point> öğesine ekleyin.
  13. Satırdaki adresi tek bir dize olacak şekilde satırdan çıkarın: Address1,Address2,City,State,Zip. İlk satır 1600 Amphitheater Parkway,,Mountain View,CA,94043 olmalı. Yan yana virgül varsa sorun olmaz. Bunu yapabilmek için CSV dosyasının yapısı ve adresi hangi sütunların oluşturduğu konusunda önceden bilgi sahibi olmanız gerekir.
  14. Coğrafi Kodlama için KML'de Kullanılacak Adresler bölümünde açıklanan geocoded_for_KML.py kodunu kullanarak adresi coğrafi olarak kodlayın. Bu, konumun boylamı ve enlemi olan bir dize döndürür.
  15. Bir metin düğümü oluşturun ve 14. adımdaki koordinatların değerini atayın, ardından <coordinates> öğesine ekleyin.
  16. KML dosyasını bir dosyaya yazın.
  17. Sütun adları listesini komut dosyasına bağımsız değişken olarak aktarırsanız komut dosyası, öğeleri bu sırayla ekler. Öğelerin sırası önemsemezsek list oluşturmak için dict.keys() kullanabiliriz. Ancak dict.keys(), dokümandaki orijinal siparişi korumaz. Bu bağımsız değişkeni kullanmak için alan adları listesini virgülle ayrılmış olarak aşağıdaki gibi iletin:
    python csvtokml.py Office,Address1,Address2,Address3,City,State,Zip,Phone,Fax

Örnek Python Kodu

Python 2.2 kullanarak CSV dosyasından KML dosyası oluşturmak için örnek kod aşağıda gösterilmiştir. Uygulamayı buradan da indirebilirsiniz.


import geocoding_for_kml
import csv
import xml.dom.minidom
import sys


def extractAddress(row):
  # This extracts an address from a row and returns it as a string. This requires knowing
  # ahead of time what the columns are that hold the address information.
  return '%s,%s,%s,%s,%s' % (row['Address1'], row['Address2'], row['City'], row['State'], row['Zip'])

def createPlacemark(kmlDoc, row, order):
  # This creates a  element for a row of data.
  # A row is a dict.
  placemarkElement = kmlDoc.createElement('Placemark')
  extElement = kmlDoc.createElement('ExtendedData')
  placemarkElement.appendChild(extElement)
  
  # 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 = geocoding_for_kml.geocode(extractAddress(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)

  # Skip the header line.
  csvReader.next()
  
  for row in csvReader:
    placemarkElement = createPlacemark(kmlDoc, row, order)
    documentElement.appendChild(placemarkElement)
  kmlFile = open(fileName, 'w')
  kmlFile.write(kmlDoc.toprettyxml('  ', newl = '\n', encoding = 'utf-8'))

def main():
  # This reader opens up 'google-addresses.csv', which should be replaced with your own.
  # It creates a KML file called 'google.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 = ['Office','Address1','Address2','Address3','City','State','Zip','Phone','Fax']
  csvreader = csv.DictReader(open('google-addresses.csv'),order)
  kml = createKML(csvreader, 'google-addresses.kml', order)
if __name__ == '__main__':
  main()

Örnek KML Oluşturuldu

Bu komut dosyasının oluşturduğu KML'nin bir örneği aşağıda gösterilmektedir. Bazı<value> öğelerin içinde nasıl yalnızca boşluk olduğuna dikkat edin. Bunun nedeni, alanda veri bulunmamasıdır. Ayrıca tam örneği buradan indirebilirsiniz.

<?xml version="1.0" encoding="utf-8"?>
<kml xmlns="http://earth.google.com/kml/2.2">
  <Document>
    <Placemark>
      <ExtendedData>
        <Data name="Office">
          <value>
            Headquarters
          </value>
        </Data>
        <Data name="Address1">
          <value>
            1600 Amphitheater Parkway
          </value>
        </Data>
        <Data name="City">
          <value>
            Mountain View
          </value>
        </Data>
        <Data name="State">
          <value>
            CA
          </value>
        </Data>
        <Data name="Zip">
          <value>
            94043
          </value>
        </Data>
        <Data name="Phone">
          <value>
            650-253-0000
          </value>
        </Data>
        <Data name="Fax">
          <value>
            650-253-0001
          </value>
        </Data>
      </ExtendedData>
      <Point>
        <coordinates>
          -122.081783,37.423111
        </coordinates>
      </Point>
    </Placemark>
    ...

Ekran görüntüsü

Söz konusu KML dosyasının Google Earth'te nasıl göründüğünü gösteren ekran görüntüsünü aşağıda bulabilirsiniz. Her<Placemark> öğesinde <BalloonStyle><text> ve <description> öğesi olmadığından, balon varsayılan olarak <Data> öğelerini çizecek şekilde bir tablo stili oluşturur.

Bu komut dosyası tarafından oluşturulan KML&#39;nin ekran görüntüsü

Coğrafi Kodlama Konusu

Bu konudan "KML'de Kullanılacak Coğrafi Kodlama Adresleri" başlıklı makaleden bahsedilmiştir, ancak bu konunun tekrarlanması önemlidir. Coğrafi kodlama istekleriniz,coğrafi kodlamanın maksimum sorgu oranına ve IP'nize bağlı olarak günde 15.000 sorguya tabi olur. Ayrıca, durum kodu daha kısa süre içinde sorgulanırsa kodlayıcı tarafından 620 durum kodu döndürülür. (Durum kodlarının tam listesini burada bulabilirsiniz.) Kodlayıcıya sorguları çok hızlı göndermemek için her coğrafi kodlama isteği arasında bir gecikme belirtebilirsiniz. 620 durumu her aldığınızda bu gecikmeyi artırabilir ve sonraki adrese geçmeden önce adresi başarıyla coğrafi kodlamaya geçirdiğinizden emin olmak için while döngü kullanabilirsiniz. Bu, CSV dosyanız çok büyükse coğrafi kodlama kodunu değiştirmeniz ya da Yer İşaretleri oluşturma hızınızı takip etmeniz ve çok hızlı hareket ediyorsanız bunu yavaşlatmanız gerektiği anlamına gelir.

Sonuç

Artık bir CSV dosyasından KML dosyası oluşturmak için Python'u kullanabilirsiniz. Sağlanan kod kullanılarak KML dosyası yalnızca Google Earth'te çalışır. Bu özelliği <ExtendedData> ve <description> yerine hem Haritalar hem de Earth'te çalışacak şekilde değiştirebilirsiniz. Bu kod örneğini XML desteği sağlayan diğer programlama dillerine dönüştürmek de kolaydır.

Tüm CSV dosyalarınızı KML'ye dönüştürmeyi tamamladığınıza göre, artık KML oluşturmak için PHP ve MySQL'i kullanma ve Genişletilmiş Veriler'de Özel Veri Ekleme gibi Google Geliştirici Kılavuzu gibi diğer KML makalelerini inceleyebilirsiniz.

Başa dön