This project has moved and is read-only. For the latest updates, please go here.

On how to use the lib?

Jan 21, 2011 at 5:56 AM
Edited Jan 21, 2011 at 5:58 AM

Hi  samcragg,

I am glad to know your good work on kml lib in C#.  I have  some practical questions using your because I couldn't find in in the Documentation:

- How to extract polygons and their according styles?

- More on cases which polygons or other geometries with refer to <StyleMap> and other Styles within this node,...

Thanks a lot.

Best regards,

Middlevn

Jan 21, 2011 at 5:27 PM

Hi Middlevn,

Once you've loaded your root Kml element (using the KmlFile, KmzFile or Parser classes) then you can iterate over them using the Flatten extension method in the SharpKml.Engine namespace and extract which elements you want from that. Here's a quick example based on the sample from the google documentation:

using System;
using System.IO;
using System.Linq;
using System.Text;
using SharpKml.Dom;
using SharpKml.Engine;

class Program
{
    const string Xml =
@"<?xml version='1.0' encoding='UTF-8'?>
<kml xmlns='http://www.opengis.net/kml/2.2'>
  <Document>
    <name>Polygon.kml</name>
    <open>0</open>
    <Placemark>
      <name>hollow box</name>
      <Polygon id='TestPolygon'>
        <extrude>1</extrude>
        <altitudeMode>relativeToGround</altitudeMode>
        <outerBoundaryIs>
          <LinearRing>
            <coordinates>
              -122.366278,37.818844,30
              -122.365248,37.819267,30
              -122.365640,37.819861,30
              -122.366669,37.819429,30
              -122.366278,37.818844,30
            </coordinates>
          </LinearRing>
        </outerBoundaryIs>
        <innerBoundaryIs>
          <LinearRing>
            <coordinates>
              -122.366212,37.818977,30
              -122.365424,37.819294,30
              -122.365704,37.819731,30
              -122.366488,37.819402,30
              -122.366212,37.818977,30
            </coordinates>
          </LinearRing>
        </innerBoundaryIs>
      </Polygon>
    </Placemark>
  </Document>
</kml>";

    static void Main(string[] args)
    {
        // First get the Kml into a KmlFile object
        KmlFile file;
        using (var stream = new MemoryStream(ASCIIEncoding.UTF8.GetBytes(Xml)))
        {
            file = KmlFile.Load(stream);
        }

        // Use the Flatten extension method to iterate over all the elements
        // then use the Linq extension OfType to select only Polygons
        foreach (var poly in file.Root.Flatten().OfType<Polygon>())
        {
            Console.WriteLine(poly.Id);
        }

        Console.ReadKey();
    }
}

Hope that helps but if you get stuck then post some code and/or Kml and I'll try and help.

Sam

Jan 22, 2011 at 8:43 AM

thanks Sam a lot for your prompt response. About my second question,  I want to find the styles for the polygons to decide how to draw them, how should I use your lib? I guess that what I should do is querying the file.Styles collection 2 times for each polygon? Is there any other more effective way?

<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://earth.google.com/kml/2.2">
<Document>
	<name>Test</name>
	<open>1</open>
	<Style id="sn_ylw-pushpin">
		<IconStyle>
			<scale>1.1</scale>
			<Icon>
				<href>http://maps.google.com/mapfiles/kml/pushpin/ylw-pushpin.png</href>
			</Icon>
			<hotSpot x="20" y="2" xunits="pixels" yunits="pixels"/>
		</IconStyle>
		<LineStyle>
			<color>ffff0000</color>
			<width>3</width>
		</LineStyle>
		<PolyStyle>
			<color>ffff0000</color>
		</PolyStyle>
	</Style>
	<Style id="sh_ylw-pushpin0">
		<IconStyle>
			<scale>1.3</scale>
			<Icon>
				<href>http://maps.google.com/mapfiles/kml/pushpin/ylw-pushpin.png</href>
			</Icon>
			<hotSpot x="20" y="2" xunits="pixels" yunits="pixels"/>
		</IconStyle>
		<LineStyle>
			<color>ffff5555</color>
		</LineStyle>
		<PolyStyle>
			<color>ffffffaa</color>
		</PolyStyle>
	</Style>
	<StyleMap id="msn_ylw-pushpin">
		<Pair>
			<key>normal</key>
			<styleUrl>#sn_ylw-pushpin2</styleUrl>
		</Pair>
		<Pair>
			<key>highlight</key>
			<styleUrl>#sh_ylw-pushpin3</styleUrl>
		</Pair>
	</StyleMap>
	<Style id="sh_ylw-pushpin">
		<IconStyle>
			<scale>1.3</scale>
			<Icon>
				<href>http://maps.google.com/mapfiles/kml/pushpin/ylw-pushpin.png</href>
			</Icon>
			<hotSpot x="20" y="2" xunits="pixels" yunits="pixels"/>
		</IconStyle>
		<LineStyle>
			<color>ff0000ff</color>
			<width>3</width>
		</LineStyle>
		<PolyStyle>
			<color>ff0000ff</color>
		</PolyStyle>
	</Style>
	<StyleMap id="msn_ylw-pushpin0">
		<Pair>
			<key>normal</key>
			<styleUrl>#sn_ylw-pushpin1</styleUrl>
		</Pair>
		<Pair>
			<key>highlight</key>
			<styleUrl>#sh_ylw-pushpin</styleUrl>
		</Pair>
	</StyleMap>
	<StyleMap id="msn_ylw-pushpin00">
		<Pair>
			<key>normal</key>
			<styleUrl>#sn_ylw-pushpin00</styleUrl>
		</Pair>
		<Pair>
			<key>highlight</key>
			<styleUrl>#sh_ylw-pushpin0</styleUrl>
		</Pair>
	</StyleMap>
	<StyleMap id="msn_ylw-pushpin1">
		<Pair>
			<key>normal</key>
			<styleUrl>#sn_ylw-pushpin0</styleUrl>
		</Pair>
		<Pair>
			<key>highlight</key>
			<styleUrl>#sh_ylw-pushpin4</styleUrl>
		</Pair>
	</StyleMap>
	<Style id="sn_ylw-pushpin0">
		<IconStyle>
			<scale>1.1</scale>
			<Icon>
				<href>http://maps.google.com/mapfiles/kml/pushpin/ylw-pushpin.png</href>
			</Icon>
			<hotSpot x="20" y="2" xunits="pixels" yunits="pixels"/>
		</IconStyle>
	</Style>
	<Style id="sh_ylw-pushpin1">
		<IconStyle>
			<scale>1.3</scale>
			<Icon>
				<href>http://maps.google.com/mapfiles/kml/pushpin/ylw-pushpin.png</href>
			</Icon>
			<hotSpot x="20" y="2" xunits="pixels" yunits="pixels"/>
		</IconStyle>
		<LineStyle>
			<color>ffff0000</color>
			<width>3</width>
		</LineStyle>
		<PolyStyle>
			<color>ffff0000</color>
		</PolyStyle>
	</Style>
	<Style id="sh_ylw-pushpin2">
		<IconStyle>
			<scale>1.3</scale>
			<Icon>
				<href>http://maps.google.com/mapfiles/kml/pushpin/ylw-pushpin.png</href>
			</Icon>
			<hotSpot x="20" y="2" xunits="pixels" yunits="pixels"/>
		</IconStyle>
		<LineStyle>
			<color>ff0000ff</color>
		</LineStyle>
		<PolyStyle>
			<color>ff0055ff</color>
		</PolyStyle>
	</Style>
	<Style id="sh_ylw-pushpin3">
		<IconStyle>
			<scale>1.3</scale>
			<Icon>
				<href>http://maps.google.com/mapfiles/kml/pushpin/ylw-pushpin.png</href>
			</Icon>
			<hotSpot x="20" y="2" xunits="pixels" yunits="pixels"/>
		</IconStyle>
		<LineStyle>
			<color>ff00aa00</color>
			<width>3</width>
		</LineStyle>
		<PolyStyle>
			<color>ff00aa55</color>
		</PolyStyle>
	</Style>
	<StyleMap id="msn_ylw-pushpin2">
		<Pair>
			<key>normal</key>
			<styleUrl>#sn_ylw-pushpin3</styleUrl>
		</Pair>
		<Pair>
			<key>highlight</key>
			<styleUrl>#sh_ylw-pushpin2</styleUrl>
		</Pair>
	</StyleMap>
	<Style id="sn_ylw-pushpin1">
		<IconStyle>
			<scale>1.1</scale>
			<Icon>
				<href>http://maps.google.com/mapfiles/kml/pushpin/ylw-pushpin.png</href>
			</Icon>
			<hotSpot x="20" y="2" xunits="pixels" yunits="pixels"/>
		</IconStyle>
		<LineStyle>
			<color>ff0000ff</color>
			<width>3</width>
		</LineStyle>
		<PolyStyle>
			<color>ff0000ff</color>
		</PolyStyle>
	</Style>
	<Style id="sn_ylw-pushpin00">
		<IconStyle>
			<scale>1.1</scale>
			<Icon>
				<href>http://maps.google.com/mapfiles/kml/pushpin/ylw-pushpin.png</href>
			</Icon>
			<hotSpot x="20" y="2" xunits="pixels" yunits="pixels"/>
		</IconStyle>
		<LineStyle>
			<color>ffff5555</color>
		</LineStyle>
		<PolyStyle>
			<color>ffffffaa</color>
		</PolyStyle>
	</Style>
	<Style id="sn_ylw-pushpin2">
		<IconStyle>
			<scale>1.1</scale>
			<Icon>
				<href>http://maps.google.com/mapfiles/kml/pushpin/ylw-pushpin.png</href>
			</Icon>
			<hotSpot x="20" y="2" xunits="pixels" yunits="pixels"/>
		</IconStyle>
		<LineStyle>
			<color>ff00aa00</color>
			<width>3</width>
		</LineStyle>
		<PolyStyle>
			<color>ff00aa55</color>
		</PolyStyle>
	</Style>
	<Style id="sn_ylw-pushpin3">
		<IconStyle>
			<scale>1.1</scale>
			<Icon>
				<href>http://maps.google.com/mapfiles/kml/pushpin/ylw-pushpin.png</href>
			</Icon>
			<hotSpot x="20" y="2" xunits="pixels" yunits="pixels"/>
		</IconStyle>
		<LineStyle>
			<color>ff0000ff</color>
		</LineStyle>
		<PolyStyle>
			<color>ff0055ff</color>
		</PolyStyle>
	</Style>
	<StyleMap id="msn_ylw-pushpin3">
		<Pair>
			<key>normal</key>
			<styleUrl>#sn_ylw-pushpin</styleUrl>
		</Pair>
		<Pair>
			<key>highlight</key>
			<styleUrl>#sh_ylw-pushpin1</styleUrl>
		</Pair>
	</StyleMap>
	<Style id="sh_ylw-pushpin4">
		<IconStyle>
			<scale>1.3</scale>
			<Icon>
				<href>http://maps.google.com/mapfiles/kml/pushpin/ylw-pushpin.png</href>
			</Icon>
			<hotSpot x="20" y="2" xunits="pixels" yunits="pixels"/>
		</IconStyle>
	</Style>
	<Placemark>
		<name>sprlee1</name>
		<styleUrl>#msn_ylw-pushpin00</styleUrl>
		<Polygon>
			<tessellate>1</tessellate>
			<outerBoundaryIs>
				<LinearRing>
					<coordinates>
-81.97340987665346,26.71272250605091,0 -81.95763371948945,26.71216571726161,0 -81.95763450506257,26.72514960776137,0 -81.97382620846342,26.71791499613803,0 -81.97340987665346,26.71272250605091,0 </coordinates>
				</LinearRing>
			</outerBoundaryIs>
		</Polygon>
	</Placemark>
	<Placemark>
		<name>xclarea1</name>
		<styleUrl>#msn_ylw-pushpin2</styleUrl>
		<Polygon>
			<tessellate>1</tessellate>
			<outerBoundaryIs>
				<LinearRing>
					<coordinates>
-81.96925642064318,26.71511629491467,0 -81.96618972656277,26.71631091802701,0 -81.96467905210392,26.71560680044782,0 -81.96400046129179,26.71767990026917,0 -81.96890541224811,26.71711226225752,0 -81.96925642064318,26.71511629491467,0 </coordinates>
				</LinearRing>
			</outerBoundaryIs>
		</Polygon>
	</Placemark>
	<Placemark>
		<name>sprtest1</name>
		<description>blue</description>
		<styleUrl>#msn_ylw-pushpin3</styleUrl>
		<Polygon>
			<tessellate>1</tessellate>
			<outerBoundaryIs>
				<LinearRing>
					<coordinates>
-81.99449646468275,26.70808570792848,0 -81.9924058035669,26.68943306730647,0 -81.98753409838633,26.68953816211705,0 -81.98753479581188,26.69855425265836,0 -81.98219905374211,26.69834832961173,0 -81.98278069822342,26.71347610183918,0 -81.99449646468275,26.70808570792848,0 </coordinates>
				</LinearRing>
			</outerBoundaryIs>
		</Polygon>
	</Placemark>
	<Placemark>
		<name>sprtest2</name>
		<description>green</description>
		<styleUrl>#msn_ylw-pushpin</styleUrl>
		<Polygon>
			<tessellate>1</tessellate>
			<outerBoundaryIs>
				<LinearRing>
					<coordinates>
-81.97141312060192,26.69948856426641,0 -81.96201863773115,26.69876386242139,0 -81.96178649715775,26.70974732280946,0 -81.9709493195152,26.71088694863553,0 -81.97094929748658,26.71036890246528,0 -81.97152918940338,26.70933276857975,0 -81.97187707699888,26.70726049281144,0 -81.97152911420449,26.70529172067737,0 -81.97106516974327,26.7035301529669,0 -81.97083319789586,26.70290841839665,0 -81.9714131231265,26.7010430424892,0 -81.97141312060192,26.69948856426641,0 </coordinates>
				</LinearRing>
			</outerBoundaryIs>
		</Polygon>
	</Placemark>
	<Placemark>
		<name>xcltest2</name>
		<description>red</description>
		<styleUrl>#msn_ylw-pushpin0</styleUrl>
		<Polygon>
			<tessellate>1</tessellate>
			<outerBoundaryIs>
				<LinearRing>
					<coordinates>
-81.96804960218817,26.70467021572241,0 -81.96538201554701,26.70549918269019,0 -81.96561398126849,26.70788242814875,0 -81.96793362565781,26.70798604532848,0 -81.96804960218817,26.70467021572241,0 </coordinates>
				</LinearRing>
			</outerBoundaryIs>
		</Polygon>
	</Placemark>
	<Placemark>
		<name>twrt1</name>
		<description>tower1</description>
		<LookAt>
			<longitude>-81.96572996519537</longitude>
			<latitude>26.71865767360295</latitude>
			<altitude>0</altitude>
			<range>10256.47558177165</range>
			<tilt>0</tilt>
			<heading>-1.04428392224447</heading>
			<altitudeMode>relativeToGround</altitudeMode>
		</LookAt>
		<styleUrl>#msn_ylw-pushpin1</styleUrl>
		<Point>
			<coordinates>-81.94635777393806,26.72404409296669,0</coordinates>
		</Point>
	</Placemark>
</Document>
</kml>

Jan 22, 2011 at 10:05 PM
Edited Jan 22, 2011 at 10:07 PM

Ok, first the Kml you posted uses the old namespace so won't be supported by default, however, there is an easy workaround (using the Parser class, but you'll need to download the latest version from the "Source Code" tab above).

To get the style we're going to use the StyleResolver class to help us, which finds the style (or inherited if it doesn't contain one) of a Feature (only Features in Kml can have a Style.)

using System;
using System.Linq;
using SharpKml.Base;
using SharpKml.Dom;
using SharpKml.Engine;

class Program
{
    const string Xml =
@"<?xml version='1.0' encoding='UTF-8'?>
<kml xmlns='http://earth.google.com/kml/2.2'>
<Document>

<!-- As you posted above -->

</Document>
</kml>";

    static void Main(string[] args)
    {
        // Load the Kml into a Parser because it uses the old namespace...
        Parser parser = new Parser();
        parser.ParseString(Xml, false); // Ignore namespaces

        // We need a file for the StyleResolver
        KmlFile file = KmlFile.Create(parser.Root, false);        
        foreach (var poly in file.Root.Flatten().OfType<Polygon>())
        {
            // We can't apply a style to a polygon, only a feature, so search for
            // a Feature in the polygon's hierarchy
            Feature feature = poly.GetParent<Feature>();
            if (feature != null) // Make sure we found one
            {
                Style style = StyleResolver.CreateResolvedStyle(
                    feature,
                    file,
                    StyleState.Normal, // or StyleState.Highlight
                    false); // Don't look for external references

                if (style != null)
                {
                    Console.WriteLine(style.Id);
                }
            }
        }

        Console.ReadKey();
    }
}

As noted, I didn't copy all the Kml you posted in this post to keep it short, but when run it should output:

sn_ylw-pushpin00
sn_ylw-pushpin3
sn_ylw-pushpin
sn_ylw-pushpin2
sn_ylw-pushpin1
Jan 24, 2011 at 1:24 AM

Thank you very much, Sam. I got it.

Oct 2, 2011 at 1:37 PM

Sam, I'm trying to read some files using the old namespace, however they are also compressed (kmz) files. Is there a quick work around based on the above code? I have a substantial number of files to process, so unzipping them all is not the preferred solution.

Oct 3, 2011 at 1:33 AM

@salmmon: I haven't got access to a computer for a few days (using my smart-phone) but you should be able to do something with the KmzFile.ReadKml method to get the Kml text then use the previously posted code to process it.

Oct 9, 2011 at 3:59 PM

Hi Sam

Managed to get code working with KMZs based on the above. I'm now trying to traverse the tree and discovering that whilst Flatten gives me the set of all nodes below the root (or chosen element) (as it should), I can't just get the .Children(), as Children() are protected and the get accessor for the Children property is inaccessible.

Am I being stupid, or am I unable to do a depth first traverse of the tree from my code, outside the Element class?

(that is, replacing Flatten() with Children() in the otherwise working code fragment below gives code that won't compile due to the protection level of SharpKml.Dom.Element.Children)

            KmlFile kmlf = KmlFile.Create(parser.Root, true);
            Element curnode = kmlf.Root;
            foreach (Element child in curnode.Children())
            {
                Debug.WriteLine(child.ToString());
            }
Oct 10, 2011 at 4:50 AM

The Flatten extension method does a depth first traversal - I'm guessing that if you want to access the Children property you want to do a breadth first traversal.

Can I ask what it is you're trying to achieve? Maybe there is an abstract base class that might be able to fulfil your needs (for example, the Container class has a Features property that can be used to store multiple elements).

If you can reply in a new discussion that would be a help to organise things as I think we've ventured off topic from the original poster :)