My goal is to remove placemarks in a kml file read with sharpkml and save the xml as new kml.
What I tried
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?
Ok... A Placemark
is a Feature
, and Feature
s go in Container
s... And in Container
s there is an aptly named .RemoveFeature()
... Sadly the method uses the .Id
to find the Feature
, but not all Feature
s 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);
}