Mengonversi file CSV ke KML

Mano Marks, Tim Google Geo API
Maret 2008

Tujuan

Tutorial ini menguraikan dasar-dasar cara membuat KML dari data Nilai yang Dipisahkan Koma (CSV) menggunakan Python. Data CSV adalah salah satu format file yang paling umum digunakan saat ini. Sebagian besar spreadsheet dan database dapat membaca dan menulis file CSV. Format sederhananya dapat diedit di editor teks. Banyak bahasa pemrograman, seperti Python, memiliki library khusus untuk membaca dan menulis file CSV. Oleh karena itu, media ini merupakan media yang bagus untuk pertukaran data dalam jumlah besar.

Meskipun contoh kode dalam tutorial ini ada di Python, contoh kode tersebut dapat diadaptasi ke sebagian besar bahasa pemrograman lainnya. Tutorial ini menggunakan kode dari Alamat Geocoding untuk Digunakan di KML untuk mengubah alamat menjadi koordinat bujur/lintang. Ini juga menggunakan elemen <ExtendedData> baru KML 2.2, dan memanfaatkan template balon yang diuraikan dalam Menambahkan Data Kustom. Dengan demikian, KML yang dihasilkan saat ini tidak didukung di Google Maps atau aplikasi lainnya yang menggunakan KML, tetapi kodenya dapat disesuaikan untuk menghasilkan KML yang kompatibel dengan Maps.

Data Contoh

Untuk tutorial ini, gunakan file google-addresses.csv sebagai contoh file CSV. File ini memiliki semua alamat, nomor telepon, dan nomor faks berbagai kantor Google di AS. Berikut adalah teks file:

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,

Perhatikan bahwa setiap baris merupakan serangkaian string teks yang dipisahkan koma. Setiap koma membatasi kolom; setiap baris memiliki jumlah koma yang sama. Baris pertama berisi nama kolom secara berurutan. Misalnya, blok teks pertama di setiap baris adalah kolom "Office", yang kedua "Address1", dll. Python dapat mengubahnya menjadi kumpulan dicts yang disebut DictReader yang memungkinkan Anda melewati setiap baris. Contoh kode ini mengandalkan Anda untuk mengetahui struktur data Anda sebelumnya, tetapi Anda dapat menambahkan beberapa pengendali dasar untuk meneruskan struktur kolom secara dinamis.

Mengurai File CSV

Modul xml.dom.minidom Python menyediakan alat yang bagus untuk membuat dokumen XML, dan karena KML adalah XML, Anda akan banyak menggunakannya dalam tutorial ini. Anda membuat elemen dengan createElement atau createElementNS, dan menambahkannya ke elemen lain dengan appendChild. Berikut adalah langkah-langkah untuk menguraikan file CSV dan membuat file KML.

  1. Impor geocoding_for_kml.py ke modul.
  2. Buat DictReader untuk file CSV. DictReader adalah kumpulan dicts, satu untuk setiap baris.
  3. Buat dokumen menggunakan xml.dom.minidom.Document() Python.
  4. Buat elemen <kml> root menggunakan createElementNS.
  5. Tambahkan dokumen tersebut ke dokumen.
  6. Buat elemen <Document> menggunakan createElement.
  7. Tambahkan elemen tersebut ke elemen <kml> menggunakan appendChild.
  8. Untuk setiap baris, buat elemen <Placemark>, lalu tambahkan ke elemen <Document>.
  9. Untuk setiap kolom di setiap baris, buat elemen <ExtendedData> dan tambahkan ke elemen <Placemark> yang Anda buat di langkah 8.
  10. Buat elemen <Data>, lalu tambahkan ke elemen <ExtendedData>. Berikan elemen <Data> pada atribut nama, dan tetapkan nilai nama kolom menggunakan setAttribute.
  11. Buat elemen <value> dan tambahkan ke elemen <Data>. Buat node teks, dan tetapkan nilai kolom menggunakan createTextNode. Tambahkan node teks ke elemen <value>.
  12. Buat elemen <Point> dan tambahkan ke elemen <Placemark>. Buat elemen <coordinates> dan tambahkan ke elemen <Point>.
  13. Ekstrak alamat dari baris sehingga hanya berupa satu string dalam format ini: Address1,Address2,City,State,Zip. Jadi, baris pertama adalah 1600 Amphitheater Parkway,,Mountain View,CA,94043. Tidak masalah jika ada koma di samping satu sama lain. Untuk melakukannya, Anda harus memiliki pengetahuan sebelumnya tentang struktur file CSV dan kolom mana yang membentuk alamat.
  14. Lakukan geocoding pada alamat menggunakan kode geocoding_for_kml.py yang dijelaskan dalam Alamat Geocoding untuk Digunakan di KML. Tindakan ini menampilkan string yang merupakan bujur dan lintang lokasi.
  15. Buat node teks dan tetapkan nilai koordinat pada langkah 14, lalu tambahkan ke elemen <coordinates>.
  16. Menulis dokumen KML ke file.
  17. Jika Anda meneruskan daftar nama kolom sebagai argumen ke skrip, skrip akan menambahkan elemen dalam urutan tersebut. Jika urutan elemen tidak penting, kita dapat menggunakan dict.keys() untuk menghasilkan list. Namun, dict.keys() tidak mempertahankan urutan asli dari dokumen. Untuk menggunakan argumen ini, teruskan daftar nama kolom sebagai daftar yang dipisahkan koma, seperti ini:
    python csvtokml.py Office,Address1,Address2,Address3,City,State,Zip,Phone,Fax

Contoh Kode Python

Kode contoh untuk membuat file KML dari file CSV menggunakan Python 2.2 ditampilkan di bawah ini. Anda juga dapat mendownloadnya di sini.


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()

Contoh KML Dibuat

Contoh KML yang dibuat skrip ini ditampilkan di bawah. Perhatikan bahwa beberapa<value> elemen hanya memiliki spasi kosong di dalamnya. Hal ini karena kolom tersebut tidak memiliki data apa pun di dalamnya. Anda juga dapat mendownload contoh lengkapnya di sini.

<?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>
    ...

Screen shot

Berikut adalah screenshot tampilan file KML tersebut di Google Earth. Karena setiap elemen <Placemark> tidak memiliki elemen <BalloonStyle><text> dan <description>, balon secara default ditetapkan ke gaya tabel, yang digambar pada elemen <Data>.

Screenshot KML yang dibuat oleh skrip ini

Pertimbangan Geocoding

Ini disebutkan dalam "Alamat Geocoding untuk Digunakan di KML", tetapi berulang. Permintaan geocoding Anda akan tunduk pada kecepatan kueri maksimum geocoder dan 15.000 kueri per hari berdasarkan IP Anda. Selain itu, kode status 620 akan ditampilkan oleh geocoder jika Anda membuat kueri lebih cepat daripada yang dapat ditangani. (Daftar lengkap kode status tersedia di sini.) Untuk memastikan Anda tidak mengirim kueri terlalu cepat ke geocoder, Anda dapat menentukan penundaan di antara setiap permintaan geocode. Anda dapat meningkatkan penundaan ini setiap kali menerima status 620, dan menggunakan loop while untuk memastikan Anda berhasil melakukan geocoding pada alamat sebelum melakukan iterasi ke alamat berikutnya. Ini berarti bahwa jika file CSV Anda sangat besar, Anda mungkin harus memodifikasi kode geocoding, atau melacak seberapa cepat Anda membuat Penanda Letak dan memperlambatnya jika kecepatannya terlalu cepat.

Kesimpulan

Sekarang Anda dapat menggunakan Python untuk membuat file KML dari file CSV. Dengan menggunakan kode yang diberikan, file KML hanya akan berfungsi di Google Earth. Anda dapat memodifikasinya agar berfungsi di Maps dan Earth menggunakan <description>, bukan <ExtendedData>. Selain itu, mudah untuk mengonversi contoh kode ini ke bahasa pemrograman lain yang menyediakan dukungan XML.

Setelah selesai mengonversi semua file CSV ke KML, Anda dapat melihat artikel KML lainnya, seperti Menggunakan PHP dan MySQL untuk membuat KML serta artikel Panduan Google Developers tentang ExtendedData, Menambahkan Data Kustom.

Kembali ke atas