CSV फ़ाइलों को KML में बदलना

मनो मार्क्स, Google Geo APIs टीम
मार्च 2008

मकसद

इस ट्यूटोरियल में, Python का इस्तेमाल करके कॉमा सेपरेटेड वैल्यू (CSV) डेटा से KML बनाने के तरीके के बारे में बुनियादी जानकारी दी गई है. CSV डेटा, आज के समय में सबसे ज़्यादा इस्तेमाल होने वाले फ़ाइल फ़ॉर्मैट में से एक है. ज़्यादातर स्प्रेडशीट और डेटाबेस, CSV फ़ाइलों को पढ़ और लिख सकते हैं. इसके सामान्य फ़ॉर्मैट में, टेक्स्ट एडिटर में बदलाव किया जा सकता है. Python जैसी कई प्रोग्रामिंग भाषाओं में, CSV फ़ाइलों को पढ़ने और लिखने के लिए खास लाइब्रेरी होती हैं. इसलिए, यह बड़ी मात्रा में डेटा का आदान-प्रदान करने का एक बेहतरीन तरीका है.

इस ट्यूटोरियल में कोड के सैंपल Python में दिए गए हैं. हालांकि, इन्हें ज़्यादातर अन्य प्रोग्रामिंग भाषाओं के हिसाब से भी इस्तेमाल किया जा सकता है. इस ट्यूटोरियल में, KML में इस्तेमाल करने के लिए पतों को जियोकोड करना लेख में दिए गए कोड का इस्तेमाल किया गया है. इससे किसी पते को अक्षांश/देशांतर निर्देशांकों में बदला जा सकता है. यह KML 2.2 के नए <ExtendedData> एलिमेंट का इस्तेमाल करता है. साथ ही, कस्टम डेटा जोड़ने में बताए गए बलून टेंप्लेटिंग का फ़ायदा लेता है. इसलिए, अभी Google Maps या KML का इस्तेमाल करने वाले अन्य ऐप्लिकेशन में, इस KML का इस्तेमाल नहीं किया जा सकता. हालांकि, कोड में बदलाव करके, Maps के साथ काम करने वाली KML बनाई जा सकती है.

सैंपल डेटा

इस ट्यूटोरियल के लिए, google-addresses.csv फ़ाइल को सैंपल CSV फ़ाइल के तौर पर इस्तेमाल करें. इस फ़ाइल में, अमेरिका में मौजूद Google के अलग-अलग ऑफ़िस के पते, फ़ोन नंबर, और फ़ैक्स नंबर दिए गए हैं. फ़ाइल का टेक्स्ट यहां दिया गया है:

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,

ध्यान दें कि हर लाइन में टेक्स्ट स्ट्रिंग की एक सीरीज़ होती है, जिसे कॉमा लगाकर अलग किया जाता है. हर कॉमा, एक फ़ील्ड को अलग करता है. हर लाइन में कॉमा की संख्या एक जैसी होती है. पहली लाइन में फ़ील्ड के नाम क्रम से दिए गए हैं. उदाहरण के लिए, हर लाइन में टेक्स्ट का पहला ब्लॉक "Office" फ़ील्ड है, दूसरा "Address1" वगैरह. Python इसे dicts के कलेक्शन में बदल सकता है. इसे DictReader कहा जाता है. इससे आपको हर लाइन में जाने की सुविधा मिलती है. इस कोड सैंपल के लिए, आपको अपने डेटा के स्ट्रक्चर के बारे में पहले से पता होना चाहिए. हालांकि, फ़ील्ड स्ट्रक्चर को डाइनैमिक तरीके से पास करने के लिए, कुछ बुनियादी हैंडलर जोड़े जा सकते हैं.

CSV फ़ाइल को पार्स करना

Python का xml.dom.minidom मॉड्यूल, एक्सएमएल दस्तावेज़ बनाने के लिए बेहतरीन टूल उपलब्ध कराता है. साथ ही, KML एक एक्सएमएल फ़ाइल है. इसलिए, इस ट्यूटोरियल में इसका इस्तेमाल काफ़ी ज़्यादा किया जाएगा. createElement या createElementNS की मदद से कोई एलिमेंट बनाया जाता है. इसके बाद, appendChild की मदद से उसे किसी दूसरे एलिमेंट में जोड़ा जाता है. CSV फ़ाइल को पार्स करने और KML फ़ाइल बनाने का तरीका यहां दिया गया है.

  1. geocoding_for_kml.py को अपने मॉड्यूल में इंपोर्ट करें.
  2. CSV फ़ाइलों के लिए DictReader बनाएं. DictReader, dicts का कलेक्शन होता है. हर लाइन के लिए एक dicts होता है.
  3. Python के xml.dom.minidom.Document() का इस्तेमाल करके दस्तावेज़ बनाएं.
  4. createElementNS. का इस्तेमाल करके, रूट <kml> एलिमेंट बनाएं
  5. इसे दस्तावेज़ में जोड़ें.
  6. createElement का इस्तेमाल करके, <Document> तत्व बनाएं.
  7. इसे appendChild का इस्तेमाल करके, <kml> एलिमेंट से जोड़ें.
  8. हर लाइन के लिए, एक <Placemark> एलिमेंट बनाएं और उसे <Document> एलिमेंट में जोड़ें.
  9. हर लाइन के हर कॉलम के लिए, एक <ExtendedData> एलिमेंट बनाएं और उसे चरण 8 में बनाए गए <Placemark> एलिमेंट में जोड़ें.
  10. <Data> एलिमेंट बनाएं और उसे <ExtendedData> एलिमेंट में जोड़ें. <Data> एलिमेंट को नाम एट्रिब्यूट दें. साथ ही, setAttribute का इस्तेमाल करके, इसे कॉलम के नाम की वैल्यू असाइन करें.
  11. <value> एलिमेंट बनाएं और उसे <Data> एलिमेंट में जोड़ें. एक टेक्स्ट नोड बनाएं और createTextNode का इस्तेमाल करके, उसे कॉलम की वैल्यू असाइन करें. टेक्स्ट नोड को <value> एलिमेंट में जोड़ें.
  12. <Point> एलिमेंट बनाएं और उसे <Placemark> एलिमेंट में जोड़ें. <coordinates> एलिमेंट बनाएं और उसे <Point> एलिमेंट में जोड़ें.
  13. लाइन से पता निकालें, ताकि यह इस फ़ॉर्मैट में एक स्ट्रिंग बन जाए: पता1,पता2,शहर,राज्य,पिन कोड. इसलिए, पहली लाइन 1600 Amphitheater Parkway,,Mountain View,CA,94043 होगी. अगर एक साथ कई कॉमा हैं, तो भी कोई समस्या नहीं है. ध्यान दें कि ऐसा करने के लिए, आपको CSV फ़ाइल के स्ट्रक्चर और यह जानकारी होनी चाहिए कि कौनसे कॉलम में पता मौजूद है.
  14. KML में इस्तेमाल करने के लिए पतों को जियोकोड करना में बताए गए geocoding_for_kml.py कोड का इस्तेमाल करके, पते को जियोकोड करें. इससे एक स्ट्रिंग मिलती है. यह जगह का देशांतर और अक्षांश होता है.
  15. एक टेक्स्ट नोड बनाएं और उसे चरण 14 में दिए गए कोऑर्डिनेट की वैल्यू असाइन करें. इसके बाद, उसे <coordinates> एलिमेंट में जोड़ें.
  16. KML दस्तावेज़ को किसी फ़ाइल में लिखें.
  17. अगर स्क्रिप्ट में कॉलम के नामों की सूची को आर्ग्युमेंट के तौर पर पास किया जाता है, तो स्क्रिप्ट उन एलिमेंट को उसी क्रम में जोड़ेगी. अगर हमें एलिमेंट के क्रम से कोई फ़र्क़ नहीं पड़ता, तो हम dict.keys() का इस्तेमाल करके list बना सकते हैं. हालांकि, dict.keys() से दस्तावेज़ में मौजूद ओरिजनल क्रम को बनाए नहीं रखा जाता. इस आर्ग्युमेंट का इस्तेमाल करने के लिए, फ़ील्ड के नामों की सूची को कॉमा लगाकर अलग की गई सूची के तौर पर पास करें. जैसे:
    python csvtokml.py Office,Address1,Address2,Address3,City,State,Zip,Phone,Fax

Python कोड का सैंपल

Python 2.2 का इस्तेमाल करके, CSV फ़ाइल से KML फ़ाइल बनाने के लिए सैंपल कोड यहां दिया गया है. इसे यहां से भी डाउनलोड किया जा सकता है.


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

सैंपल KML बनाया गया

इस स्क्रिप्ट से बनाई गई KML का सैंपल यहां दिया गया है. ध्यान दें कि कुछ<value> एलिमेंट में सिर्फ़ खाली जगह है. ऐसा इसलिए है, क्योंकि फ़ील्ड में कोई डेटा नहीं था. पूरे सैंपल को यहां से भी डाउनलोड किया जा सकता है.

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

स्क्रीनशॉट

यहां एक स्क्रीनशॉट दिया गया है. इसमें दिखाया गया है कि Google Earth में KML फ़ाइल कैसी दिखती है. हर <Placemark> एलिमेंट में कोई <BalloonStyle><text> और कोई <description> एलिमेंट नहीं होता. इसलिए, बलून डिफ़ॉल्ट रूप से टेबल स्टाइल में होता है. यह <Data> एलिमेंट का इस्तेमाल करता है.

इस स्क्रिप्ट से बनाई गई KML का स्क्रीनशॉट

जियोकोडिंग से जुड़ी बातें

इस बारे में "KML में इस्तेमाल करने के लिए पतों को जियोकोड करना" लेख में बताया गया है. हालांकि, हम इसे फिर से दोहरा रहे हैं. आपके जियोकोडिंग अनुरोधों पर, जियोकोडर के ज़्यादा से ज़्यादा क्वेरी रेट और आपके आईपी के आधार पर हर दिन 15,000 क्वेरी की सीमा लागू होगी. इसके अलावा, अगर जियोकोडर से बहुत तेज़ी से क्वेरी की जाती है, तो वह 620 वाला स्टेटस कोड दिखाएगा. (स्टेटस कोड की पूरी सूची यहां उपलब्ध है.) यह पक्का करने के लिए कि जियोकोडर को बहुत तेज़ी से क्वेरी न भेजी जाएं, हर जियोकोड अनुरोध के बीच देरी तय की जा सकती है. हर बार 620 स्टेटस मिलने पर, इस देरी को बढ़ाया जा सकता है. साथ ही, while लूप का इस्तेमाल करके यह पक्का किया जा सकता है कि आपने अगले पते पर जाने से पहले, किसी पते को जियोकोड कर लिया है. इसका मतलब है कि अगर आपकी CSV फ़ाइल बहुत बड़ी है, तो आपको जियोकोडिंग कोड में बदलाव करना पड़ सकता है. इसके अलावा, आपको यह भी ट्रैक करना होगा कि प्लेस मार्क कितनी तेज़ी से बनाए जा रहे हैं. अगर प्लेस मार्क बहुत तेज़ी से बनाए जा रहे हैं, तो आपको इसकी स्पीड कम करनी होगी.

नतीजा

अब Python का इस्तेमाल करके, CSV फ़ाइल से KML फ़ाइल बनाई जा सकती है. दिए गए कोड का इस्तेमाल करके, KML फ़ाइल सिर्फ़ Google Earth में काम करेगी. <ExtendedData> की जगह <description> का इस्तेमाल करके, इसे Maps और Earth, दोनों में काम करने के लिए बदला जा सकता है. इस कोड सैंपल को, XML के साथ काम करने वाली किसी भी दूसरी प्रोग्रामिंग भाषा में आसानी से बदला जा सकता है.

अब आपने सभी CSV फ़ाइलों को KML में बदल लिया है. इसलिए, आपको KML के बारे में अन्य लेख पढ़ने चाहिए. जैसे, KML बनाने के लिए PHP और MySQL का इस्तेमाल करना और ExtendedData के बारे में Google डेवलपर गाइड का लेख, कस्टम डेटा जोड़ना.

वापस सबसे ऊपर जाएं