【问题标题】:Create kml file using xml elements使用 xml 元素创建 kml 文件
【发布时间】:2013-03-15 10:46:43
【问题描述】:

我想在 c# 中创建一个 kml 文件。现在我有两个问题:

  1. 在 xml 文件中添加 kml 元素以便在我的 kml 文件中包含以下行的 synatx 是什么?

    <kml xmlns="http://www.opengis.net/kml/2.2">
    
  2. 我有一个点数组,我想形成一个线串。我想如何在 xml 中为 kml 文件填充坐标元素?。以下是我目前的代码。

代码

public void MakeKmlFile(string line)
{
    CoordinateCollection coordinates = new CoordinateCollection();

    char[] delimiterLine = { '|' };
    char[] delimiterPoint = { ',' };
    string[] route = line.Split(delimiterLine);

    foreach (string point in route)
    {
        string[] route_point = line.Split(delimiterPoint);
        double lat = double.Parse(route_point[1]);
        double lon = double.Parse(route_point[0]);
        coordinates.Add(new Vector(lat, lon));
    }

    XmlTextWriter writer = new XmlTextWriter("route.xml", System.Text.Encoding.UTF8);
    writer.Formatting = Formatting.Indented;
    writer.WriteStartElement("Document");
    writer.WriteStartElement("Folder");
    writer.WriteStartElement("name");
    writer.WriteString("route");
    writer.WriteEndElement();
    writer.WriteStartElement("Placemark");
    writer.WriteStartElement("Style");
    writer.WriteStartElement("LineStyle");
    writer.WriteStartElement("color");
    writer.WriteString("ff0000ff");
    writer.WriteEndElement();
    writer.WriteEndElement();
    writer.WriteStartElement("PolyStyle");
    writer.WriteStartElement("fill");
    writer.WriteString("2");
    writer.WriteEndElement();
    writer.WriteEndElement();
    writer.WriteEndElement();
    writer.WriteStartElement("LineString");
    writer.WriteStartElement("coordinates");

这是我得到的结果:

<?xml version="1.0" encoding="utf-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2">
  <Document>
    <Name>Points.kml</Name>
    <Placemark />
    <Placemark />
    <Placemark />
    <Placemark />
    <Placemark />
  </Document>

【问题讨论】:

  • 请注意,PolyStyle 填充元素的值为 1 或 0 =>“2”无效。

标签: c# xml kml


【解决方案1】:

您可以像创建普通 XML 文档一样创建 KML 文档

    XmlDocument xDoc = new XmlDocument();
    XmlDeclaration xDec = xDoc.CreateXmlDeclaration("1.0", "utf-8", null);

    XmlElement rootNode = xDoc.CreateElement("kml");
    rootNode.SetAttribute("xmlns", @"http://www.opengis.net/kml/2.2");
    xDoc.InsertBefore(xDec, xDoc.DocumentElement);
    xDoc.AppendChild(rootNode);
    XmlElement docNode = xDoc.CreateElement("Document");
    rootNode.AppendChild(docNode);

    XmlElement nameNodeMain = xDoc.CreateElement("Name");
    XmlText nameTextMain = xDoc.CreateTextNode("Points.kml");
    docNode.AppendChild(nameNodeMain);
    nameNodeMain.AppendChild(nameTextMain);

这为您的文档设置了基本结构,然后您需要做的就是添加每个地标(最好通过循环完成)

    char[] delimiterLine = { '|' };
    char[] delimiterPoint = { ',' };
    string[] places = line.Split(delimiterLine);
    for (int i = 0; i < places.length; i++)
        {
            string[] placeMark = places[i].split(delimiterPoint);
            XmlElement placeNode = xDoc.CreateElement("Placemark");
            docNode.AppendChild(placeNode);

            XmlElement nameNode = xDoc.CreateElement("Name");
            XmlText nameText = xDoc.CreateTextNode(placeMark[0]);
            placeNode.AppendChild(nameNode);
            nameNode.AppendChild(nameText);

            XmlElement descNode = xDoc.CreateElement("Description");
            XmlText descText = xDoc.CreateTextNode(placeMark[1]);
            placeNode.AppendChild(descNode);
            descNode.AppendChild(descText);

            XmlElement pointNode = xDoc.CreateElement("Point");
            placeNode.AppendChild(pointNode);

            XmlElement coordNode = xDoc.CreateElement("coordinates");
            XmlText coordText = xDoc.CreateTextNode(string.Format("{0},{1}", placeMark[2], placeMark[3]));
            pointNode.AppendChild(coordNode);
            coordNode.AppendChild(coordText);
        }
        return xDoc;

我之前没有在 KML 中使用过 LineStrings,但我怀疑执行此操作的代码如下所示:

    XmlDocument xDoc = new XmlDocument();
    XmlDeclaration xDec = xDoc.CreateXmlDeclaration("1.0", "utf-8", null);

    XmlElement rootNode = xDoc.CreateElement("kml");
    rootNode.SetAttribute("xmlns", @"http://www.opengis.net/kml/2.2");
    xDoc.InsertBefore(xDec, xDoc.DocumentElement);
    xDoc.AppendChild(rootNode);
    XmlElement docNode = xDoc.CreateElement("Document");
    rootNode.AppendChild(docNode);

    XmlElement nameNodeMain = xDoc.CreateElement("Name");
    XmlText nameTextMain = xDoc.CreateTextNode("Points.kml");
    docNode.AppendChild(nameNodeMain);
    nameNodeMain.AppendChild(nameTextMain);

XmlElement placeNode = xDoc.CreateElement("Placemark");
docNode.AppendChild(placeNode);

XmlElement nameNode = xDoc.CreateElement("Name");
XmlText nameText = xDoc.CreateTextNode("Test line");
placeNode.AppendChild(nameNode);
nameNode.AppendChild(nameText);

XmlElement lineStringNode = xDoc.CreateElement("LineString");
placeNode.AppendChild(lineStringNode);

XmlElement coordNode = xDoc.CreateElement("coordinates");

char[] delimiterLine = { '|' };
    char[] delimiterPoint = { ',' };
    string[] places = line.Split(delimiterLine);
    for (int i = 0; i < places.length; i++)
    {
    string[] placeMark = places[i].split(delimiterPoint);

    XmlText coordText = xDoc.CreateTextNode(string.Format("{0},{1}", placeMark[0], placeMark[1]));
    pointNode.AppendChild(coordNode);
   }


coordNode.AppendChild(coordText);

xDoc.Save("./KML/");

它基本上涉及移动我以前的代码并为 KML 文件中所需的每个主要元素创建一个 XmlElement,然后在将它们拆分为行字符串后遍历坐标。

【讨论】:

  • 感谢您的回复。既然我想以点数组中的线串元素结束,我该如何在每个循环的地标中处理它? @唐纳德·邓洛普
  • 我假设你的线串是“place|place|place”的格式,每个“地方”都由 place = “Name,Description,Latitude,Longitude”组成可以做的是使用从 Split("|") 收到的数组,然后执行一个 for 循环遍历该数组并使用“,”字符分割其中的每个元素。
  • 我已将 foreach 循环更改为使用线串拆分的 for 循环
  • 现在我想怎么看结果。它会保存在某个地方吗? @唐纳德·邓洛普
  • 您可以使用 xDoc.Save("Filename") 将 XML 文件保存到特定的文件目标以检查它是否正常工作
【解决方案2】:

最直接的解决方案是标记路线(线串)并将坐标附加到字符串缓冲区中,然后作为值输出。无需创建 CoordinateCollection 和单独的 Vector 对象。

注意:为了成为有效的 KML,您必须先输出经度值,然后输出用逗号 (,) 分隔的纬度,经度纬度值之间没有空格,并且空格必须可选地使用高度值分隔每个经度纬度对。

这是使用 System.Xml.XmlTextWriter 类的 C# 解决方案:

    XmlTextWriter writer = new XmlTextWriter(...);
    writer.WriteStartElement("kml", "http://www.opengis.net/kml/2.2");
    ...
    writer.WriteStartElement("LineString");
    StringBuilder sb = new StringBuilder();
    foreach (string point in route)
    {
        string[] route_point = point.Split(delimiterPoint);
        if (route_point.Length >= 2)
        {
          double lon = double.Parse(route_point[0]);
          double lat = double.Parse(route_point[1]);
          sb.Append(' ').Append(lon).Append(',').Append(lat);
          // coordinates.Add(new Vector(lat, lon));
        }
    }
    writer.WriteStartElement("coordinates");
    writer.WriteValue(sb.ToString());
    writer.WriteEndElement(); // end coordinates
    writer.WriteEndElement(); // end LineString
    writer.WriteEndElement(); // end Placemark
    ...
    writer.Close();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多