如何用LINQ读取含不一致元素的KML文件并避免空引用异常?
处理KML中Placemark的Point/LineString坐标提取(避免空引用)
问题根源
原代码直接访问Element("Point")或Element("LineString"),当目标元素不存在时返回null,后续链式访问子元素(如.Element("coordinates"))会触发System.NullReferenceException。
修改后的LINQ实现
方式1:显式判断Point/LineString(直观易读)
通过?.空条件运算符安全访问元素,用??优先级 fallback 到另一种类型的坐标:
// 注意:Google Earth导出的KML默认带命名空间,必须定义后使用 XNamespace kmlNs = "http://www.opengis.net/kml/2.2"; var placemarks = doc.Descendants(kmlNs + "Placemark") .Select(p => new { Name = p.Element(kmlNs + "Name")?.Value, Coordinates = p.Element(kmlNs + "Point")?.Element(kmlNs + "coordinates")?.Value ?? p.Element(kmlNs + "LineString")?.Element(kmlNs + "coordinates")?.Value });
方式2:统一筛选坐标容器元素(灵活扩展)
通过筛选Placemark下的Point或LineString元素,再安全提取坐标,后续新增其他类型(如Polygon)时只需修改筛选条件:
XNamespace kmlNs = "http://www.opengis.net/kml/2.2"; var placemarks = doc.Descendants(kmlNs + "Placemark") .Select(p => new { Name = p.Element(kmlNs + "Name")?.Value, Coordinates = p.Descendants() .Where(e => e.Name.LocalName is "Point" or "LineString") .FirstOrDefault() ?.Element(kmlNs + "coordinates") ?.Value });
关键说明
?.运算符:当前面的元素为null时,直接返回null,不会继续执行后续的元素访问,从根源避免空引用- 命名空间处理:必须用命名空间前缀查询元素,否则会找不到KML中的目标节点
- 坐标解析:若LineString的coordinates是多组坐标值,可后续用
Split(new[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries)分割处理
内容的提问来源于stack exchange,提问作者MatthewD
相关产品推荐
相关产品推荐

