关于地理格式数据KML的各种转换
首先看下有没有你想要的格式,没有就不要往下看了,当然,大多数文件都可以转换,除非你的文件是宇宙航天级别的复杂度,纯手工制作,尊重原创哈(2024.7.29文章更新,更新图形化界面及相应算法【cloud转JSON部分为客户定制内容,未公布】,以下文章内容为最新版本2.0)。
这里写目录标题
一、先看最终效果
这次就不放置源码文件了哈,有需要可以在文章下边复制,最终留给大家的是一个打包好的exe程序,见下图:
1. 双击运行后出现主界面
主界面可以选择文件、选择输出的格式、选择文件输出的位置,暂不支持批量操作哈,若有需要还麻烦多点几次,就可以了,当然,如果你的文件量巨大,随时可以通过文章末尾联系,支持定制。
2. 选择文件界面
注意,新版本升级后我添加了cloud文件选项,目前cloud文件仅支持转为JSON格式,且是一位朋友定制的需求(cloud转json不是通用的哈,慎用!!!)
3. 选择文件输出格式
文件的输出格式目前支持:JSON、XML、GeoGebra、CSV、Shapefile、GPX、WKT,一般来说标准的文件转换都不成问题哈,如果是定制的,建议研究下代码自行升级一下我给的算法。
4. 点击转换
这一步就不截图了,点击转换后就可以在指定的目录下边找到一个和目标文件同名的文件,但是格式已经换成了选择的输出格式。
二、关于源码
1. 核心算法说明
这里是类型转换的核心代码,若有需要可以研究下这里:
def convert_kml_to_json(self):
import xml.etree.ElementTree as ET
import json
# 读取 KML 文件
tree = ET.parse(self.selected_file)
root = tree.getroot()
# 定义命名空间
namespaces = {
'kml': 'http://www.opengis.net/kml/2.2'}
# 创建一个空的字典来存储 JSON 数据
json_data = {
'placemarks': []}
# 遍历 KML 文件中的所有 Placemark
for placemark in root.findall('.//kml:Placemark', namespaces):
placemark_data = {
}
# 获取 Placemark 名称
name = placemark.find('kml:name', namespaces)
if name is not None:
placemark_data['name'] = name.text
# 获取 Placemark 描述
description = placemark.find('kml:description', namespaces)
if description is not None:
placemark_data['description'] = description.text
# 获取 Placemark 的坐标
coordinates = placemark.find('.//kml:coordinates', namespaces)
if coordinates is not None:
coords_text = coordinates.text.strip()
coords = coords_text.split(',')
placemark_data['coordinates'] = {
'longitude': float(coords[0]),
'latitude': float(coords[1]),
'altitude': float(coords[2]) if len(coords) > 2 else 0.0
}
json_data['placemarks'].append(placemark_data)
# 生成输出文件路径
output_file = os.path.join(self.output_location,
os.path.splitext(os.path.basename(self.selected_file))[0] + '.json')
# 将数据写入 JSON 文件
with open(output_file, 'w', encoding='utf-8') as f:
json.dump(json_data, f, ensure_ascii=False, indent=4)
QMessageBox.information(self, "提示", "KML文件已成功转换为JSON")
def convert_kml_to_xml(self):
import xml.etree.ElementTree as ET
# 读取 KML 文件
tree = ET.parse(self.selected_file)
root = tree.getroot()
# 创建一个新的 XML 结构
new_root = ET.Element('ConvertedData')
placemarks_element = ET.SubElement(new_root, 'Placemarks')
# 定义命名空间
namespaces = {
'kml': 'http://www.opengis.net/kml/2.2'}
# 遍历 KML 文件中的所有 Placemark
for placemark in root.findall('.//kml:Placemark', namespaces):
placemark_element = ET.SubElement(placemarks_element, 'Placemark')
# 获取 Placemark 名称
name = placemark.find('kml:name', namespaces)
if name is not None:
name_element = ET.SubElement(placemark_element, 'Name')
name_element.text = name.text
# 获取 Placemark 描述
description = placemark.find('kml:description', namespaces)
if description is not None:
description_element = ET.SubElement(placemark_element, 'Description')
description_element.text = description.text
# 获取 Placemark 的坐标
coordinates = placemark.find('.//kml:coordinates', namespaces)
if coordinates is not None:
coords_text = coordinates.text.strip()
coords = coords_text.split(',')
coordinates_element = ET.SubElement(placemark_element, 'Coordinates')
longitude_element = ET.SubElement(coordinates_element, 'Longitude')
latitude_element = ET.SubElement(coordinates_element, 'Latitude')
altitude_element = ET.SubElement(coordinates_element, 'Altitude')
longitude_element.text = coords[0]
latitude_element.text = coords[1]
altitude_element.text = coords[2] if len(coords) > 2 else '0.0'
# 生成输出文件路径
output_file = os.path.join(self.output_location,
os.path.splitext(os.path.basename(self.selected_file))[0] + '_converted.xml')
# 将新的 XML 结构写入文件
new_tree = ET.ElementTree(new_root)
new_tree.write(output_file, encoding='utf-8', xml_declaration=True)
QMessageBox.information(self, "提示", "KML文件已成功转换为XML")
def convert_kml_to_geojson(self):
import xml.etree.ElementTree as ET
import json
# 读取 KML 文件
tree = ET.parse(self.selected_file)
root = tree.getroot()
# 定义命名空间
namespaces = {
'kml': 'http://www.opengis.net/kml/2.2'}
# 创建一个空的字典来存储 GeoJSON 数据
geojson_data = {
'type': 'FeatureCollection',
'features': []
}
# 遍历 KML 文件中的所有 Placemark
for placemark in root.findall('.//kml:Placemark', namespaces):
feature = {
'type': 'Feature',
'geometry': {
'type': 'Point',
'coordinates': []
},
'properties': {
}
}
# 获取 Placemark 名称
name = placemark.find('kml:name', namespaces)
if name is not None:
feature['properties']['name'] = name.text
# 获取 Placemark 描述
description = placemark.find('kml:description', namespaces)
if description is not None:
feature['properties']['description'] = description.text
# 获取 Placemark 的坐标
coordinates = placemark.find('.//kml:coordinates', namespaces)
if coordinates is not None:
coords_text = coordinates.text.strip()
coords = list(map(float, coords_text.split(',')))
feature['geometry']['coordinates'] = coords
geojson_data['features'].append(feature)
# 生成输出文件路径
output_file = os.path.join(self.output_location,
os.path.splitext(os.path.basename(self.selected_file))[0] + '.geojson')
# 将数据写入 GeoJSON 文件
with open(output_file, 'w', encoding='utf-8') as f:
json.dump(geojson_data, f, ensure_ascii=False, indent=4)
QMessageBox.information(self, "提示", "KML文件已成功转换为GeoJSON")
def convert_kml_to_csv(self):
import xml.etree.ElementTree as ET
import csv
# 读取 KML 文件
tree = ET.parse(self.selected_file)
root = tree.getroot()
# 定义命名空间
namespaces = {
'kml': 'http://www.opengis.net/kml/2.2'}
# 创建一个列表来存储 CSV 数据
csv_data = []
# 添加 CSV 文件的头部
csv_data.append(['Name', 'Description', 'Lo