Mengonversi file CSV ke KML

Mano Marks, Tim Google Geo API
Maret 2008

Tujuan

Tutorial ini menguraikan dasar-dasar cara membuat KML dari data Comma Separated Value (CSV) menggunakan Python. Data CSV adalah salah satu format file yang paling banyak digunakan saat ini. Sebagian besar spreadsheet dan database dapat membaca dan menulis file CSV. Formatnya yang sederhana dapat diedit di editor teks. Banyak bahasa pemrograman, seperti Python, memiliki library khusus untuk membaca dan menulis file CSV. Oleh karena itu, SDS menjadi media yang tepat untuk menukar data dalam jumlah besar.

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

Data Sampel

Untuk tutorial ini, gunakan file google-addresses.csv sebagai contoh file CSV. File ini berisi semua alamat, nomor telepon, dan nomor faks dari berbagai kantor Google di Amerika Serikat. 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 bagaimana setiap baris adalah serangkaian string teks yang dipisahkan oleh 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 menelusuri setiap baris. Contoh kode ini mengandalkan pengetahuan Anda sebelumnya tentang struktur data, tetapi Anda dapat menambahkan beberapa pengendali dasar untuk meneruskan struktur kolom secara dinamis.

Mengurai File CSV

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

  1. Impor geocoding_for_kml.py ke dalam modul Anda.
  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 ke dokumen.
  6. Buat elemen <Document> menggunakan createElement.
  7. Tambahkan 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>. Beri elemen <Data> 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 menjadi 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 yang berdekatan. Perhatikan, untuk melakukannya, Anda harus mengetahui terlebih dahulu struktur file CSV dan kolom mana yang membentuk alamat.
  14. Beri geocode pada alamat menggunakan kode geocoding_for_kml.py yang dijelaskan dalam Geocoding Alamat untuk Digunakan dalam KML. Tindakan ini akan menampilkan string yang merupakan bujur dan lintang lokasi.
  15. Buat node teks dan tetapkan nilai koordinat di langkah 14, lalu tambahkan ke elemen <coordinates>.
  16. Tulis dokumen KML ke file.
  17. Jika Anda meneruskan daftar nama kolom sebagai argumen ke skrip, skrip akan menambahkan elemen dalam urutan tersebut. Jika kita tidak peduli dengan urutan elemen, 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

Contoh kode untuk membuat file KML dari file CSV menggunakan Python 2.2 ditampilkan di bawah. 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 yang Dibuat

Contoh KML yang dibuat oleh skrip ini ditampilkan di bawah. Perhatikan bagaimana beberapa elemen<value> hanya memiliki spasi kosong. Hal ini karena kolom tidak memiliki data apa pun. 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

Di bawah ini adalah screenshot tampilan file KML tersebut di Google Earth. Karena setiap elemen <Placemark> tidak memiliki <BalloonStyle><text> dan tidak memiliki elemen <description>, balon akan menggunakan gaya tabel secara default, dengan memanfaatkan elemen <Data>.

Screenshot KML yang dibuat oleh skrip ini

Pertimbangan Geocoding

Hal ini disebutkan dalam "Geocoding Addresses for Use in KML", tetapi perlu diulang. 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 Anda menerima status 620, dan menggunakan loop while untuk memastikan Anda telah berhasil melakukan geokode alamat sebelum melakukan iterasi ke alamat berikutnya. Artinya, jika file CSV Anda sangat besar, Anda mungkin harus mengubah kode geocoding, atau melacak seberapa cepat Anda membuat Penanda Tempat dan memperlambatnya jika Anda melakukannya 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 mengubahnya agar berfungsi di Maps dan Earth menggunakan <description>, bukan <ExtendedData>. Contoh kode ini juga mudah dikonversi ke bahasa pemrograman lain yang menyediakan dukungan XML.

Setelah selesai mengonversi semua file CSV ke KML, Anda mungkin ingin membaca artikel KML lainnya, seperti Menggunakan PHP dan MySQL untuk membuat KML dan artikel Panduan Developer Google tentang ExtendedData, Menambahkan Data Kustom.

Kembali ke atas