norbert
norbert

Reputation: 335

Reading in XML/KML files using C#

I'm trying to import the kml xml Google earth file into an application, but i can't seem to get the xDocument syntax right in order to do what i want, i'm wondering if anyone could suggest a way to read in the kml xml file.

I understand the basics of xml import but can't get anything working with xDocument and Linq, ideally i'd like to get each Placemark as an object and add them to my Entity Framework driven db. Any suggestions as to how i should do this would be great, as i'm just starting out with Linq and could do with some pointers. The xml is laid out as below

<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://earth.google.com/kml/2.2">
  <Document>
    <Placemark>
      <name>XXX</name>
      <description>XXX</description>
      <styleUrl>XXX</styleUrl>
      <Point>
         <coordinates>XXX</coordinates>
      </Point>
    </Placemark>
    <Placemark>
      <name>XXX</name>
      <description>XXX</description>
      <styleUrl>XXX</styleUrl>
      <Point>
         <coordinates>XXX</coordinates>
      </Point>
    </Placemark>
  </Document>
</kml>

Upvotes: 11

Views: 27361

Answers (5)

user3190933
user3190933

Reputation: 146

Your kml file must contains

<kml xmlns="http://www.opengis.net/kml/2.2" ...

instead of

<kml xmlns="http://earth.google.com/kml/2.2"> ...

Upvotes: 0

Hassan Rahman
Hassan Rahman

Reputation: 5203

I used SharmpKml and its documentation to extract information from KML file.

using SharpKml.Dom;
using SharpKml.Engine;
using SharpKml.Dom.GX;

TextReader reader = File.OpenText(filePath);
KmlFile file = KmlFile.Load(reader);
_kml = file.Root as Kml;

sPlaceMarks[] tempPlaceMarks = new sPlaceMarks[1000];
if (_kml != null)
{
  foreach (var placemark in _kml.Flatten().OfType<Placemark>())
  {
  tempPlaceMarks[numOfPlaceMarks].Name = placemark.Name;
  tempPlaceMarks[numOfPlaceMarks].Description = placemark.Description.Text;
  tempPlaceMarks[numOfPlaceMarks].StyleUrl = placemark.StyleUrl;
  tempPlaceMarks[numOfPlaceMarks].point = placemark.Geometry as SharpKml.Dom.Point;
  tempPlaceMarks[numOfPlaceMarks].CoordinateX = tempPlaceMarks[numOfPlaceMarks].point.Coordinate.Longitude;
  tempPlaceMarks[numOfPlaceMarks].CoordinateY = tempPlaceMarks[numOfPlaceMarks].point.Coordinate.Latitude;
  tempPlaceMarks[numOfPlaceMarks].CoordinateZ = tempPlaceMarks[numOfPlaceMarks].point.Coordinate.Altitude;
  numOfPlaceMarks++;
  }

  foreach (var lookAt in _kml.Flatten().OfType<LookAt>())
  {
  Placemark placemark = (Placemark)lookAt.Parent;
  for (int i = 0; i < numOfPlaceMarks; i++)
  {
    if (placemark.Name == tempPlaceMarks[i].Name)
    {
      tempPlaceMarks[i].Name = placemark.Name;
      tempPlaceMarks[i].Description = placemark.Description.Text;
      tempPlaceMarks[i].StyleUrl = placemark.StyleUrl;
      tempPlaceMarks[i].altitude = lookAt.Altitude;
      tempPlaceMarks[i].AltitudeMode =(SharpKml.Dom.GX.AltitudeMode)lookAt.GXAltitudeMode;
      tempPlaceMarks[i].Heading = lookAt.Heading;
      tempPlaceMarks[i].Latitude = lookAt.Latitude;
      tempPlaceMarks[i].Longitude = lookAt.Longitude;
      tempPlaceMarks[i].Range = lookAt.Range;
      tempPlaceMarks[i].Tilt = lookAt.Tilt;
      break;
    }
  }
}

Upvotes: 5

L.B
L.B

Reputation: 116108

var xDoc = XDocument.Load("a.xml");
XNamespace ns = "http://earth.google.com/kml/2.2";

var placemarks = xDoc.Descendants(ns+"Placemark")
                    .Select(p => new
                    {
                        Name = p.Element(ns+"name").Value,
                        Desc = p.Element(ns+"description").Value
                    })
                    .ToList();

Upvotes: 3

Guvante
Guvante

Reputation: 19203

You didn't include any code, but I would guess that you forgot to include your namespace when referencing things. Here is an example.

Basic access:

var placemarks = xdoc.Element("kml").Element("Document").Elements("Placemark");

Using namespaces:

var ns = XNamespace.Get("http://earth.google.com/kml/2.2");
var placemarks = xdoc.Element(ns + "kml").Element(ns + "Document").Elements(ns + "Placemark");

Upvotes: 8

Jon Skeet
Jon Skeet

Reputation: 1499840

My guess is that you've forgotten to use the namespace in your LINQ to XML queries. It's easy enough to extract the data from this:

XNamespace ns = "http://earth.google.com/kml/2.2";
var doc = XDocument.Load("file.xml");
var query = doc.Root
               .Element(ns + "Document")
               .Elements(ns + "Placemark")
               .Select(x => new PlaceMark // I assume you've already got this
                       {
                           Name = x.Element(ns + "name").Value,
                           Description = x.Element(ns + "description").Value,
                           // etc
                       });

If that doesn't help, please post a complete example of what you've tried, and what went wrong.

Upvotes: 8

Related Questions