如何使用fastkml获取KML的Style及StyleMap样式信息?
KML样式解析问题:提取Style属性与处理StyleMap
问题背景
正在解析KML文件,需根据要素的样式进行分类,已成功获取要素的styleUrl,但无法提取Document中Style的详细属性(如LineStyle的color、width,PolyStyle的fill),仅能获取Style的ID。同时想了解StyleMap的处理流程是否与Style一致。
现有解析代码(获取要素)
from fastkml import kml import os with open(os.path.join(tmp_root,'doc.kml')) as file: for text in file : k = kml.KML() k.from_string(text) document = list(k.features()) print(len(document)) # 对应<Document id=xxx>,预期为1 folders = list(document[0].features()) print(folders) # 两个文件夹:一个边界、一个点 for folder in folders : features = list(folder.features()) for f in features : print(f.name) print(f.styleUrl) print(f.extended_data.elements) for attribute in f.extended_data.elements : print(attribute.name, attribute.value) # 待实现:根据styleUrl匹配Style并分类
现有Style获取代码(仅能获取ID)
stylesSection = document[0].styles() # 类似获取folders的方式 for style in stylesSection : print(style) # 输出<fastkml.styles.Style object at ...> print(style.id) # 输出styleid print(style.styles) # 输出方法引用而非实际样式数据
KML结构示例
<kml xmlns="http://www.opengis.net/kml/2.2" xmlns:gx="http://www.google.com/kml/ext/2.2" xmlns:kml="http://www.opengis.net/kml/2.2" xmlns:atom="http://www.w3.org/2005/Atom"> <Document id="IDOFDOC"> <name>NAME</name> <open>1</open> <Style id="styleid"> <LineStyle> <color>ff0000ff</color> <width>5</width> </LineStyle> <PolyStyle> <fill>0</fill> </PolyStyle> </Style> </Document> </kml>
解决方案
一、提取Style中的LineStyle/PolyStyle属性
fastkml的Style对象需调用styles()方法获取内部样式子元素,通过类型判断提取对应属性:
from fastkml.styles import LineStyle, PolyStyle stylesSection = document[0].styles() for style in stylesSection: print(f"Style ID: {style.id}") # 遍历Style下的所有样式子元素 for style_element in style.styles(): if isinstance(style_element, LineStyle): print(f"LineStyle 颜色: {style_element.color}") print(f"LineStyle 宽度: {style_element.width}") elif isinstance(style_element, PolyStyle): print(f"PolyStyle 填充状态: {style_element.fill}")
注意:必须调用style.styles()而非直接访问style.styles(后者是方法引用);需提前导入对应样式类以确保类型判断准确。
二、处理StyleMap的流程
StyleMap与Style的处理逻辑不同,StyleMap用于关联"normal"(常态)和"highlight"(高亮)两种Style,核心是解析其<Pair>元素:
from fastkml.styles import StyleMap, Pair style_maps = document[0].style_maps() for style_map in style_maps: print(f"StyleMap ID: {style_map.id}") # 遍历StyleMap下的Pair元素 for pair in style_map.pairs: if isinstance(pair, Pair): print(f"状态类型: {pair.key}") # 值为"normal"或"highlight" print(f"关联Style的URL: {pair.style_url}")
进阶优化:构建样式字典快速匹配
为便于根据要素的styleUrl快速查找对应样式,可提前将所有Style和StyleMap整理为字典:
# 构建Style字典:key为Style ID,value为样式属性集合 style_dict = {} for style in document[0].styles(): style_props = {} for elem in style.styles(): if isinstance(elem, LineStyle): style_props["LineStyle"] = {"color": elem.color, "width": elem.width} elif isinstance(elem, PolyStyle): style_props["PolyStyle"] = {"fill": elem.fill} style_dict[style.id] = style_props # 构建StyleMap字典:key为StyleMap ID,value为状态与Style ID的映射 style_map_dict = {} for sm in document[0].style_maps(): map_props = {} for pair in sm.pairs: # 去除style_url中的#号,匹配Style ID map_props[pair.key] = pair.style_url.lstrip("#") style_map_dict[sm.id] = map_props # 处理要素时直接匹配样式 for folder in folders: for f in list(folder.features()): target_id = f.styleUrl.lstrip("#") if target_id in style_dict: print(f"要素{f.name}的样式: {style_dict[target_id]}") elif target_id in style_map_dict: # 获取常态下的Style normal_style_id = style_map_dict[target_id].get("normal") if normal_style_id in style_dict: print(f"要素{f.name}的默认样式: {style_dict[normal_style_id]}")
内容的提问来源于stack exchange,提问作者postgrease
相关产品推荐
相关产品推荐

