Delete a Placemark and save the whole kml minus the placemark into a new file

276 Views Asked by At

My goal is to remove placemarks in a kml file read with sharpkml and save the xml as new kml.

What I tried

  • RemoveChildren -> Not found
  • AddUpdate with DeleteCollection -> Not working

And

using SharpKml.Base;
using SharpKml.Dom;
using SharpKml.Engine;

           
TextReader i_test = File.OpenText(@"test.kml");
KmlFile k_test = KmlFile.Load(i_test);
Kml l_test = k_test.Root as Kml;
var serializer = new Serializer();
if (l_test != null)
{
    foreach (var ort_u in l_test.Flatten().OfType<Placemark>())
    {
        Placemark p_u = ort_u;
        foreach(var einh in ort_u.ExtendedData.Data)
        {
            if (einh.Name == "teststring")
            {
                    var update = new Update();
                    update.AddUpdate(new DeleteCollection(){ p_u });
                    serializer.Serialize(l_test);
                    Console.WriteLine(serializer.Xml.Length);
            }
        }
    }
}

None of them works.

How do I delete a Placemark using SharpKml and save the whole kml minus the placemark in a new file?

1

There are 1 best solutions below

3
On BEST ANSWER

Ok... A Placemark is a Feature, and Features go in Containers... And in Containers there is an aptly named .RemoveFeature()... Sadly the method uses the .Id to find the Feature, but not all Features have an Id... But this we can solve. We set a temporary Id (Guid.NewGuid().ToString()) that is more or less guaranteed to be unique (Guid are more or less guaranteed to be unique), and we use this Id to remove the Feature.

Note that I had to add a .ToArray() in the foreach, because you can't modify a collection that you are going through, but with the .ToArray() we go through a "copy" of the collection, while we remove the elements from the original.

foreach (var placemark in kml.Flatten().OfType<Placemark>().ToArray())
{
    if (placemark.Name == "Simple placemark")
    {
        placemark.Id = Guid.NewGuid().ToString();
        ((Container)placemark.Parent).RemoveFeature(placemark.Id);
    }

    Console.WriteLine(placemark.Name);
}

I've opened a bug on the github of SharpKml about this thing.

For saving:

using (var stream = File.Create("output.kml"))
{
    var ser = new Serializer();
    ser.Serialize(kml, stream);
}