kml" />

C# 程序自动批量生成 google maps 的KML文件

系统 2293 0

google maps 的 KML 文件可以用于静态的地图标注,在某些应用中,我们手上往往有成百上千个地址,我们需要把这些地址和描述批量标注到 google maps 上去,如果手工来做,太耗时间,在这里我写了一个程序批量来生成这个 KML 文件。

首先看一下 KML 文件的格式:

    
      <?
    
    
      xml
    
    
      version
    
    
      ="1.0"
    
    
      encoding
    
    
      ="UTF-8"
    
    ?
    
      >
    
    
      <
    
    
      kml
    
    
      xmlns
    
    
      ="http://www.google.com/earth/kml/2"
    
    
      >
    
    
      <
    
    
      Document
    
    
      >
    
    
      <
    
    
      name
    
    
      >
    
    kml_sample2.kml
    
      </
    
    
      name
    
    
      >
    
    
      <
    
    
      Style
    
    
      id
    
    
      ="red"
    
    
      >
    
    
      <
    
    
      IconStyle
    
    
      >
    
    
      <
    
    
      Icon
    
    
      >
    
    
      <
    
    
      href
    
    
      >
    
    http://www.google.com/intl/en_us/mapfiles/ms/icons/red-dot.png
    
      </
    
    
      href
    
    
      >
    
    
      </
    
    
      Icon
    
    
      >
    
    
      </
    
    
      IconStyle
    
    
      >
    
    
      </
    
    
      Style
    
    
      >
    
    
      <
    
    
      Style
    
    
      id
    
    
      ="green"
    
    
      >
    
    
      <
    
    
      IconStyle
    
    
      >
    
    
      <
    
    
      Icon
    
    
      >
    
    
      <
    
    
      href
    
    
      >
    
    http://www.google.com/intl/en_us/mapfiles/ms/icons/green-dot.png
    
      </
    
    
      href
    
    
      >
    
    
      </
    
    
      Icon
    
    
      >
    
    
      </
    
    
      IconStyle
    
    
      >
    
    
      </
    
    
      Style
    
    
      >
    
    
      <
    
    
      Style
    
    
      id
    
    
      ="blue"
    
    
      >
    
    
      <
    
    
      IconStyle
    
    
      >
    
    
      <
    
    
      Icon
    
    
      >
    
    
      <
    
    
      href
    
    
      >
    
    http://www.google.com/intl/en_us/mapfiles/ms/icons/blue-dot.png
    
      </
    
    
      href
    
    
      >
    
    
      </
    
    
      Icon
    
    
      >
    
    
      </
    
    
      IconStyle
    
    
      >
    
    
      </
    
    
      Style
    
    
      >
    
    
      <
    
    
      Placemark
    
    
      >
    
    
      <
    
    
      name
    
    
      >
    
    Google Inc.
    
      </
    
    
      name
    
    
      >
    
    
      <
    
    
      description
    
    
      ><!
    
    [CDATA[
      Google Inc.
    
      <
    
    
      br
    
    
      />
    
    
      1600 Amphitheatre Parkway
    
      <
    
    
      br
    
    
      />
    
    
      Mountain View, CA 94043
    
      <
    
    
      br
    
    
      />
    
    
      Phone: +1 650-253-0000
    
      <
    
    
      br
    
    
      />
    
    
      Fax: +1 650-253-0001
    
      <
    
    
      br
    
    
      />
    
    
      <
    
    
      p
    
    
      >
    
    Home page: 
    
      <
    
    
      a
    
    
      href
    
    
      ="http://www.google.com"
    
    
      >
    
    www.google.com
    
      </
    
    
      a
    
    
      ></
    
    
      p
    
    
      >
    
    
    ]]
    
      >
    
    
      </
    
    
      description
    
    
      >
    
    
      <
    
    
      styleUrl
    
    
      >
    
    #red
    
      </
    
    
      styleUrl
    
    
      >
    
    
      <
    
    
      Point
    
    
      >
    
    
      <
    
    
      coordinates
    
    
      >
    
    -122.0841430, 37.4219720, 0
    
      </
    
    
      coordinates
    
    
      >
    
    
      </
    
    
      Point
    
    
      >
    
    
      </
    
    
      Placemark
    
    
      >
    
    
      <
    
    
      Placemark
    
    
      >
    
    
      <
    
    
      name
    
    
      >
    
    Yahoo! Inc.
    
      </
    
    
      name
    
    
      >
    
    
      <
    
    
      description
    
    
      ><!
    
    [CDATA[
      Yahoo! Inc.
    
      <
    
    
      br
    
    
      />
    
    
      701 First Avenue
    
      <
    
    
      br
    
    
      />
    
    
      Sunnyvale, CA 94089
    
      <
    
    
      br
    
    
      />
    
    
      Tel: (408) 349-3300
    
      <
    
    
      br
    
    
      />
    
    
      Fax: (408) 349-3301
    
      <
    
    
      br
    
    
      />
    
    
      <
    
    
      p
    
    
      >
    
    Home page: 
    
      <
    
    
      a
    
    
      href
    
    
      ="http://yahoo.com"
    
    
      >
    
    http://yahoo.com
    
      </
    
    
      a
    
    
      ></
    
    
      p
    
    
      >
    
    
      ]]
    
      >
    
    
      </
    
    
      description
    
    
      >
    
    
      <
    
    
      styleUrl
    
    
      >
    
    #green
    
      </
    
    
      styleUrl
    
    
      >
    
    
      <
    
    
      Point
    
    
      >
    
    
      <
    
    
      coordinates
    
    
      >
    
    -122.0250403,37.4163228
    
      </
    
    
      coordinates
    
    
      >
    
    
      </
    
    
      Point
    
    
      >
    
    
      </
    
    
      Placemark
    
    
      >
    
    
      </
    
    
      Document
    
    
      >
    
    
      </
    
    
      kml
    
    
      >
    
  

这个是一个典型的用于google maps 的 KML 文件,(注意不同应用的KML 格式会有所不同,比如 google earth 的 kml 格式就复杂得多)

从这个kml 文件格式来看,其实它就是一个 xml 文件,我们只要自动生成这个文件中各个元素的信息就可以得到这个xml  文件。这里其实最大的问题是如何自动通过地址获取经纬度坐标。值得庆幸的是 google 提供了这方面的 api 函数。google api 获取地理坐标的官方例子见: geocodingapi

我的实现稍微复杂一些,因为我需要在函数中为不同的位置自动分配颜色

 

      
           1:  
      
      
        /// <summary>
      
    
      
           2:  
      
      
        /// Generate placemark by address description
      
    
      
           3:  
      
      
        /// </summary>
      
    
      
           4:  
      
      
        /// <param name="addrDescription">address and description</param>
      
    
      
           5:  
      
      
        /// <returns>if no matched, return false</returns>
      
    
      
           6:  
      
      
        public
      
      
        bool
      
       Generate(AddressDescription addrDescription)
    
      
           7:  
      
              {
    
      
           8:  
      
                  _LastErrorOrWarning = 
      
        null
      
      ;
    
      
           9:  
      
       
    
      
          10:  
      
                  Thread.Sleep(DelayInMs);
    
      
          11:  
      
       
    
      
          12:  
      
                  List<GeographicCoordinate> coordinates = Geocoding.Geocode(addrDescription.Address);
    
      
          13:  
      
       
    
      
          14:  
      
      
        if
      
       (coordinates.Count == 0)
    
      
          15:  
      
                  {
    
      
          16:  
      
                      _LastErrorOrWarning = 
      
        string
      
      .Format(
      
        "Address:{0}, Description:{1} does not find the coordinates, please make sure the address is correctly."
      
      ,
    
      
          17:  
      
                          addrDescription.Address, addrDescription.Description);
    
      
          18:  
      
       
    
      
          19:  
      
      
        return
      
      
        false
      
      ;
    
      
          20:  
      
                  }
    
      
          21:  
      
       
    
      
          22:  
      
      
        if
      
       (coordinates.Count > 1)
    
      
          23:  
      
                  {
    
      
          24:  
      
                      _LastErrorOrWarning = 
      
        string
      
      .Format(
      
        "Address:{0}, Description:{1} has more than one coordinates."
      
      ,
    
      
          25:  
      
                          addrDescription.Address, addrDescription.Description);
    
      
          26:  
      
                  }
    
      
          27:  
      
       
    
      
          28:  
      
      
        string
      
       colorId = Colors[_ColorIndex];
    
      
          29:  
      
       
    
      
          30:  
      
                  _ColorIndex++;
    
      
          31:  
      
       
    
      
          32:  
      
      
        if
      
       (_ColorIndex >= Colors.Count)
    
      
          33:  
      
                  {
    
      
          34:  
      
                      _ColorIndex = 0;
    
      
          35:  
      
                  }
    
      
          36:  
      
       
    
      
          37:  
      
                  _Kml.Document.Add(
      
        new
      
       Placemark(addrDescription.Address, addrDescription.Description, colorId,
    
      
          38:  
      
                      coordinates[0].Latitude, coordinates[0].Longitude));
    
      
          39:  
      
       
    
      
          40:  
      
      
        return
      
      
        true
      
      ;
    
      
          41:  
      
              }
    

 

第32行有个bug,应该是 >=  ,我原来写成 > 了,博客中我改过来了,源码我就不改了。

如上代码,第12行就是通过GeocodingApi 获取指定地址的物理坐标,由于有时候获取不到坐标,有时候由于地址不确切,有多个坐标,所以我加了一个错误和警告的属性,用于调用者得到相关的信息。

_Kml 这个对象是一个 Kml 类的实例,这个类用于生成 KML 文件结构,并可以保存到KML文件中。这个类在后面介绍。

下面的 _Color 部分是自动的顺序分配标注点的颜色,我为了省事,在代码中写死了4种颜色,你也可以修改代码增加颜色或其他图标。

标注颜色这里其实还有一个问题,就是如果让相邻的节点显示不同颜色,这个算法比较复杂了,我没有实现,各位如果有兴趣可以思考一下这个怎么做。

好了,最大的问题解决了,剩下就是写 xml  文件了,这个很简单,我就不深入讲了,直接把代码贴出来。

    
      using
    
     System;

    
      using
    
     System.Collections.Generic;

    
      using
    
     System.Linq;

    
      using
    
     System.Text;

    
      using
    
     System.Xml;

    
      using
    
     System.Xml.Serialization;

    
      using
    
     System.IO;


    
      namespace
    
     GenerateKML
{
    
    
      public
    
    
      class
    
     Placemark
    {
        
    
      public
    
    
      class
    
     KMLPoint
        {
            
    
      public
    
     KMLPoint()
            {
            }

            
    
      public
    
     KMLPoint(
    
      double
    
     latitude, 
    
      double
    
     longitude)
            {
                SetCoordinates(latitude, longitude);
            }

            
    
      private
    
    
      string
    
     _coordinates;

            
    
      public
    
    
      void
    
     SetCoordinates(
    
      double
    
     latitude, 
    
      double
    
     longitude)
            {
                _coordinates = longitude.ToString() + 
    
      ","
    
     + latitude.ToString();
            }

            
    
      public
    
    
      string
    
     coordinates
            {
                get
                {
                    
    
      return
    
     _coordinates;
                }

                set
                {
                    _coordinates = 
    
      value
    
    ;
                }
            }
        }

        [XmlElement(
    
      "name"
    
    )]
        
    
      public
    
    
      string
    
     Name { get; set; }

        [XmlElement(
    
      "description"
    
    )]
        
    
      public
    
    
      string
    
     Description { get; set; }

        [XmlElement(
    
      "styleUrl"
    
    )]
        
    
      public
    
    
      string
    
     StyleUrl { get; set; }

        
    
      public
    
     KMLPoint Point { get; set; }

        
    
      public
    
     Placemark()
        {
        }

        
    
      public
    
     Placemark(
    
      string
    
     name, 
    
      string
    
     description, 
    
      string
    
     styleUrl,
            
    
      double
    
     latitude, 
    
      double
    
     longitude)
        {
            Name = name;
            Description = description;
            StyleUrl = styleUrl;

            Point = 
    
      new
    
     KMLPoint(latitude, longitude);
        }

    }

    
    
      public
    
    
      class
    
     kml
    {
        [XmlIgnore]
        
    
      string
    
     Name { get; set; }


        List<Placemark> _Placemarks = 
    
      new
    
     List<Placemark>();

        [XmlArray()]
        
    
      public
    
     List<Placemark> Document
        {
            get
            {
                
    
      return
    
     _Placemarks;
            }

            set
            {
                _Placemarks = 
    
      value
    
    ;
            }
        }

        
    
      public
    
     kml()
        {
        }

        
    
      public
    
     kml(
    
      string
    
     name)
        {
            Name = name;
        }

        
    
      private
    
     XmlNode GetColorStyle(XmlDocument xmlDoc,  
    
      string
    
     color)
        {
            XmlNode style = xmlDoc.CreateNode(XmlNodeType.Element, 
    
      "Style"
    
    , 
    
      ""
    
    );
            XmlAttribute attr = style.OwnerDocument.CreateAttribute(
    
      "id"
    
    );
            attr.Value = color;
            style.Attributes.Append(attr);

            XmlNode iconStyle = xmlDoc.CreateNode(XmlNodeType.Element, 
    
      "IconStyle"
    
    , 
    
      ""
    
    );
            XmlNode icon = xmlDoc.CreateNode(XmlNodeType.Element, 
    
      "Icon"
    
    , 
    
      ""
    
    );
            XmlNode href = xmlDoc.CreateNode(XmlNodeType.Element, 
    
      "href"
    
    , 
    
      ""
    
    );
            href.InnerText = 
    
      string
    
    .Format(
    
      "http://www.google.com/intl/en_us/mapfiles/ms/icons/{0}-dot.png"
    
    ,
                color);
            
            
            style.AppendChild(iconStyle);
            iconStyle.AppendChild(icon);
            icon.AppendChild(href);

            
    
      return
    
     style;
        }


        
    
      public
    
    
      void
    
     SaveToFile(
    
      string
    
     xml)
        {
            
    
      using
    
     (FileStream fs = 
    
      new
    
     FileStream(xml, FileMode.Create, FileAccess.ReadWrite))
            {
                
    
      using
    
     (StreamWriter sw = 
    
      new
    
     StreamWriter(fs, System.Text.Encoding.UTF8))
                {
                    XmlSerializer serializer = 
    
      new
    
     XmlSerializer(
    
      this
    
    .GetType());
                    serializer.Serialize(sw, 
    
      this
    
    );
                }
            }


            XmlDocument xmlDoc = 
    
      new
    
     XmlDocument();
            xmlDoc.Load(xml);
            xmlDoc.CreateXmlDeclaration(
    
      "1.0"
    
    , 
    
      "utf-8"
    
    , 
    
      null
    
    );

            XmlNode documentNode = xmlDoc.SelectSingleNode(
    
      @"/kml/Document"
    
    );

            XmlNode nameNode = xmlDoc.CreateNode(XmlNodeType.Element, 
    
      "name"
    
    , 
    
      ""
    
    );
            nameNode.InnerText = 
    
      this
    
    .Name;

            XmlNode placeMarkNode = documentNode.FirstChild;
            documentNode.InsertBefore(nameNode, placeMarkNode);

            documentNode.InsertBefore(GetColorStyle(xmlDoc, 
    
      "red"
    
    ), placeMarkNode);
            documentNode.InsertBefore(GetColorStyle(xmlDoc, 
    
      "green"
    
    ), placeMarkNode);
            documentNode.InsertBefore(GetColorStyle(xmlDoc, 
    
      "blue"
    
    ), placeMarkNode);
            documentNode.InsertBefore(GetColorStyle(xmlDoc, 
    
      "yellow"
    
    ), placeMarkNode);

            XmlNode kmlNode = xmlDoc.SelectSingleNode(
    
      @"/kml"
    
    );

            XmlAttribute attr = kmlNode.OwnerDocument.CreateAttribute(
    
      "xmlns"
    
    );
            attr.Value = 
    
      "http://earth.google.com/kml/2.0"
    
    ;

            kmlNode.Attributes.Append(attr);

            xmlDoc.Save(xml);
        }
    }

}

  

下面看一下调用的方法,使用者如果不想仔细研究细节,那就关注这个就可以了,调用方法非常简单

      
           1:  
      
      
        static
      
      
        void
      
       Main(
      
        string
      
      [] args)
    
      
           2:  
      
              {
    
      
           3:  
      
                  Generator kmlGenerator = 
      
        new
      
       Generator(
      
        "Test"
      
      );
    
      
           4:  
      
       
    
      
           5:  
      
                  kmlGenerator.Generate(
      
        new
      
       AddressDescription(
      
        "1600 Amphitheatre Parkway, Mountain View, CA 94043"
      
      ,
    
      
           6:  
      
      
        "Google"
      
      ));
    
      
           7:  
      
       
    
      
           8:  
      
      
        if
      
       (!
      
        string
      
      .IsNullOrEmpty(kmlGenerator.LastErrorOrWarning))
    
      
           9:  
      
                  {
    
      
          10:  
      
                      Console.WriteLine(kmlGenerator.LastErrorOrWarning);
    
      
          11:  
      
                  }
    
      
          12:  
      
       
    
      
          13:  
      
                  kmlGenerator.Generate(
      
        new
      
       AddressDescription(
      
        "1 Microsoft Way, Redmond, WA 98052"
      
      ,
    
      
          14:  
      
      
        "Microsoft"
      
      ));
    
      
          15:  
      
       
    
      
          16:  
      
      
        if
      
       (!
      
        string
      
      .IsNullOrEmpty(kmlGenerator.LastErrorOrWarning))
    
      
          17:  
      
                  {
    
      
          18:  
      
                      Console.WriteLine(kmlGenerator.LastErrorOrWarning);
    
      
          19:  
      
                  }
    
      
          20:  
      
       
    
      
          21:  
      
                  kmlGenerator.Generate(
      
        new
      
       AddressDescription(
      
        "1601 S. California Ave., Palo Alto, CA 95304"
      
      ,
    
      
          22:  
      
      
        "Facebook"
      
      ));
    
      
          23:  
      
       
    
      
          24:  
      
      
        if
      
       (!
      
        string
      
      .IsNullOrEmpty(kmlGenerator.LastErrorOrWarning))
    
      
          25:  
      
                  {
    
      
          26:  
      
                      Console.WriteLine(kmlGenerator.LastErrorOrWarning);
    
      
          27:  
      
                  }
    
      
          28:  
      
       
    
      
          29:  
      
                  kmlGenerator.Generate(
      
        new
      
       AddressDescription(
      
        "701 First Ave, Sunnyvale, CA 94089"
      
      ,
    
      
          30:  
      
      
        "Yahoo"
      
      ));
    
      
          31:  
      
       
    
      
          32:  
      
      
        if
      
       (!
      
        string
      
      .IsNullOrEmpty(kmlGenerator.LastErrorOrWarning))
    
      
          33:  
      
                  {
    
      
          34:  
      
                      Console.WriteLine(kmlGenerator.LastErrorOrWarning);
    
      
          35:  
      
                  }
    
      
          36:  
      
       
    
      
          37:  
      
                  kmlGenerator.Save(
      
        "test.kml"
      
      );
    
      
          38:  
      
              }
    
      
          39:  
      
          }
    
       
    
      第三行,实例化 KML 生成器,并指定一个名字,这个名字对于 kml 文档中的 name 字段。
    
      第五行,在kml 文件中标注 google 总部的地址
    
      第八行,判断是否有最新的错误,每次执行第五行的Generate 方法,会将最新错误清空,所以这里永远是得到最近一次调用 Generate 方法的错误或警告。
    
      后面以此类推了。
    
      最后 Save 到一个kml文件中就OK了。
    
       
    
      最后,我们可以把这个 kml 文件导入到我们自己创建的 google map 中。这个在 google maps 里面有相应的导入功能,这里就不介绍了。
    
       
    
      完整源码下载
    
       
    
       
    
      注意源码中 app.config 文件中
    
       
    
      
        <
      
      
        add
      
      
        key
      
      
        ="GeocodingApi.Key"
      
      
        value
      
      
        ="google api key"
      
      
        />
      
      
        <
      
      
        add
      
      
        key
      
      
        ="GeocodingApi.Url"
      
      
        value
      
      
        ="http://maps.google.com/maps/geo?"
      
      
        />
      
    

GeocodingApi.key 这里要填写你自己的 google api key,你可以在 google  网站上获取,地址如下:

http://code.google.com/apis/maps/signup.html

 

       
    

C# 程序自动批量生成 google maps 的KML文件


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论