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

Mano Marks, Google Geo API'leri Ekibi
Mart 2008

Hedef

Bu eğitimde, Python kullanarak virgülle ayrılmış değer (CSV) verilerinden KML oluşturmanın temelleri açıklanmaktadır. CSV verileri, günümüzde en yaygın kullanılan dosya biçimlerinden biridir. Çoğu e-tablo ve veritabanı, CSV dosyalarını hem okuyabilir hem de yazabilir. Basit biçimi, 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, büyük miktarda veri alışverişi için mükemmel bir ortamdır.

Bu eğitimdeki kod örnekleri Python dilinde olsa da diğer programlama dillerinin çoğuna uyarlanabilir. Bu eğitimde, bir adresi boylam/enlem koordinatlarına dönüştürmek için KML'de Kullanılmak Üzere Adresleri Coğrafi Kodlama bölümündeki kodlar kullanılır. Ayrıca, KML 2.2'nin yeni <ExtendedData> öğesini kullanır ve Özel Veri Ekleme bölümünde belirtilen balon şablonlarından yararlanır. Bu nedenle, oluşturulan KML şu anda Google Haritalar'da veya KML kullanan diğer uygulamalarda desteklenmemektedir ancak kod, Haritalar ile uyumlu KML oluşturacak şekilde uyarlanabilir.

Örnek Veriler

Bu eğitimde, örnek CSV dosyası olarak google-addresses.csv dosyasını kullanın. Bu dosyada, ABD'deki çeşitli Google ofislerinin adresleri, telefon numaraları ve faks numaraları yer alır. Dosyanın metni:

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 dizisi olduğuna dikkat edin. Her virgül bir alanı sınırlar ve her satırda aynı sayıda virgül bulunur. İlk satırda alanların adları sırayla yer alır. Örneğin, her satırdaki ilk metin bloğu "Ofis" alanı, ikincisi "Adres1" alanıdır. Python, bunu dicts koleksiyonuna dönüştürebilir. Bu koleksiyona DictReader adı verilir ve her satırda adım adım ilerlemenize olanak tanır. Bu kod örneği, verilerinizin yapısını önceden bildiğinizi varsayar. Ancak alan yapısını dinamik olarak iletmek için bazı temel işleyiciler ekleyebilirsiniz.

CSV dosyasını ayrıştırma

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

  1. geocoding_for_kml.py dosyasını modülünüze aktarın.
  2. CSV dosyaları için DictReader oluşturun. DictReader, her satır için bir tane olacak şekilde dicts koleksiyonudur.
  3. Python'ın xml.dom.minidom.Document() özelliğini kullanarak dokümanı oluşturun.
  4. createElementNS. kullanarak kök <kml> öğesini oluşturun.
  5. Dokümana ekleyin.
  6. createElement kullanarak <Document> öğesi oluşturun.
  7. <kml> öğesine appendChild kullanarak ekleyin.
  8. Her satır için bir <Placemark> öğesi oluşturun ve bunu <Document> öğesine ekleyin.
  9. Her satırdaki her sütun için bir <ExtendedData> öğesi oluşturun ve bunu <Placemark> öğesine ekleyin (8. adımda oluşturduğunuz).
  10. <Data> öğesi oluşturun ve bunu <ExtendedData> öğesine ekleyin. <Data> öğesine bir ad özelliği verin ve setAttribute kullanarak sütun adının değerini atayın.
  11. <value> öğesi oluşturun ve bunu <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. <Point> öğesi oluşturun ve bunu <Placemark> öğesine ekleyin. <coordinates> öğesi oluşturun ve <Point> öğesine ekleyin.
  13. Adresi satırdan çıkararak şu biçimde tek bir dize haline getirin: Adres1,Adres2,Şehir,Eyalet,Posta Kodu. Bu durumda ilk satır 1600 Amphitheater Parkway,,Mountain View,CA,94043 olur. Yan yana virgül olması sorun değildir. Bunu yapmak için CSV dosyasının yapısı ve hangi sütunların adresi oluşturduğu hakkında önceden bilgi sahibi olmanız gerekir.
  14. KML'de Kullanılmak Üzere Adreslerin Coğrafi Kodunu Belirleme başlıklı makalede açıklanan geocoding_for_kml.py kodunu kullanarak adresin coğrafi kodunu belirleyin. Bu işlev, konumun boylam ve enlemini içeren bir dize döndürür.
  15. Bir metin düğümü oluşturun ve buna 14. adımda yer alan koordinatların değerini atayın, ardından <coordinates> öğesine ekleyin.
  16. KML dokümanını bir dosyaya yazın.
  17. Sütun adlarının listesini komut dosyasına bağımsız değişken olarak iletirseniz komut dosyası öğeleri bu sırayla ekler. Öğelerin sırasını önemsemediğimiz durumlarda dict.keys() kullanarak list oluşturabiliriz. Ancak dict.keys(), dokümandaki orijinal sırayı korumaz. Bu bağımsız değişkeni kullanmak için alan adları listesini virgülle ayrılmış liste olarak şu şekilde 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şturmaya yönelik örnek kod aşağıda gösterilmiştir. Ayrıca 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ı öğelerde yalnızca boşluk olduğunu fark edin.<value> Bunun nedeni, alanın veri içermemesidir. Tam örneği buradan da 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ü

Aşağıda, söz konusu KML dosyasının Google Earth'te nasıl göründüğünü gösteren bir ekran görüntüsü yer almaktadır. Her <Placemark> öğesinde <BalloonStyle><text> ve <description> öğesi bulunmadığından balon, <Data> öğelerinden yararlanarak varsayılan olarak tablo stilinde çizilir.

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

Coğrafi Kodlama Değerlendirmesi

Bu durum "KML'de Kullanılmak Üzere Adresleri Coğrafi Kodlama" bölümünde belirtilmiş olsa da tekrar etmekte fayda var. Coğrafi kodlama istekleriniz,coğrafi kodlayıcının maksimum sorgu hızına ve IP'nize göre günde 15.000 sorguya tabi olur. Ayrıca, coğrafi kodlayıcıya işleyebileceğinden daha hızlı sorgu gönderirseniz 620 durum kodu döndürülür. (Durum kodlarının tam listesini burada bulabilirsiniz.) Coğrafi kodlayıcıya çok hızlı sorgu göndermediğinizden emin olmak için her coğrafi kodlama isteği arasında bir gecikme belirleyebilirsiniz. Bir 620 durumu aldığınız her seferde bu gecikmeyi artırabilir ve bir adresi başarıyla coğrafi olarak kodladığınızdan emin olmak için while döngüsü kullanabilirsiniz. Bu nedenle, CSV dosyanız çok büyükse coğrafi kodlama kodunu değiştirmeniz veya yer işaretlerini ne kadar hızlı oluşturduğunuzu takip etmeniz ve çok hızlıysanız bu hızı yavaşlatmanız gerekebilir.

Sonuç

Artık CSV dosyasından KML dosyası oluşturmak için Python'ı kullanabilirsiniz. Sağlanan kodu kullanarak KML dosyası yalnızca Google Earth'te çalışır. <ExtendedData> yerine <description> kullanarak hem Haritalar'da 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ürme işlemini tamamladığınıza göre KML oluşturmak için PHP ve MySQL'i kullanma ve Google Geliştirici Kılavuzu'ndaki ExtendedData ile ilgili makale olan Özel Veri Ekleme gibi diğer KML makalelerine göz atmak isteyebilirsiniz.

Başa dön