【问题标题】:How can I parse a KML file to retrieve coordinate points from a Placemark element?如何解析 KML 文件以从 Placemark 元素中检索坐标点?
【发布时间】:2019-09-03 13:02:32
【问题描述】:

我有一个 KML 文件,其中包含 GPS 坐标以及每个坐标对下一个坐标的方位。我想检索每个坐标和每个方位并将它们存储在单独的列表中。一个包含严格坐标,一个包含每个方位。

为了解决问题,我将仅列出文件中的 2 个 Placemark 元素。 我的 KML 文件如下所示:

<?xml version="1.0" encoding="utf-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2">
  <Folder>
    <Placemark>
      <name>Coordinate0</name>
      <Point>
        <coordinates>44.601788291074442,-88.048173934221268</coordinates>
      </Point>
    </Placemark>

   <!-- more coordinates and bearings fill these gaps -->

   <Placemark>
      <name>Bearing200</name>
      <Point>
        <coordinates>284.25265584263923,0</coordinates>
      </Point>
    </Placemark>
  </Folder>
</kml>

我尝试了以下方法:

 //Function that parses through the file and pulls out coordinates and bearings for each coordinate

private void ButtonTestParser_Click(object sender, EventArgs e)
{
    //load the xml file
    XDocument xmlFile = XDocument.Load("Test.kml");
    //get every placemark element in the document
    var placemarks = (from x in xmlFile.Descendants()
                      where x.Name.LocalName == "Placemark"
                  select new XElement(x)).ToList();
    //loop through each placemark and separate it into coordinates and bearings
    List<string> coordinates = new List<string>();
    string coordinate = "";
    foreach(var point in placemarks)
    {
        coordinate = (from x in point.Descendants("coordinates")
                      select x).First().Value;
        coordinates.Add(coordinate);
    }
}

我收到以下错误:

System.InvalidOperationException: '序列不包含任何元素'

【问题讨论】:

    标签: c# xml xml-parsing kml


    【解决方案1】:

    你的问题来了

    coordinate = (from x in point.Descendants("coordinates")
                  select x).First().Value;
    

    如果您查看Descendants 的定义,您会发现它需要一个XName,而不是string

    XName 只是将命名空间和元素名称连接在一起。

    因此,一个简单的解决方法是将代码编写为:

    var ns = xmlFile.Root.Name.Namespace;
    
    coordinate = (from x in point.Descendants(ns + "coordinates")
                  select x).First().Value;
    

    请注意,您可以使用相同的技术来修复您之前的代码:

    var placemarks = (from x in xmlFile.Descendants(ns + "Placemark")
    

    我冒昧地稍微重写了您的程序,因为您也不需要所有 LINQ select...from... 代码:

    //load the xml file
    var document = XDocument.Load(@"C:\temp\bob.xml");
    var ns = document.Root.Name.Namespace;
    //get every placemark element in the document
    var placemarks = document.Descendants(ns + "Placemark");
    
    //loop through each placemark and separate it into coordinates and bearings
    var coordinates = new List<string>();
    var coordinate = "";
    foreach (var point in placemarks)
    {
        coordinate = point.Descendants(ns + "coordinates").First().Value;
        coordinates.Add(coordinate);
    }
    

    【讨论】:

    • 或使用命名空间作为第二个参数point.Descendants(XName.Get("coordinates", xmlFile.Root.Name.Namespace.NamespaceName))
    • 感谢您的解决方案,效果很好。有没有一种简单的方法可以根据名称将 Point 元素分成单独的列表?我在考虑如果名称属性包含“坐标”,它将进入一个列表,否则如果它包含“轴承”,它将进入另一个列表。这与您当前的解决方案有很大不同吗?
    • 您真的应该将此作为一个新问题提出,但(非常强烈的)提示是:var bearings = document.Descendants(ns + "Placemark").Where(pm =&gt; pm.Element(ns + "name").Value.StartsWith("Bearing")).ToList();
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-27
    • 1970-01-01
    • 1970-01-01
    • 2013-11-22
    相关资源
    最近更新 更多