Giter Site home page Giter Site logo

simple-kml's Introduction

Simple KML: Cocoa parsing library for Keyhole Markup Language

Simple KML is a simple & lightweight parsing library for KML written in Objective-C for the iOS platform.

It is not meant for drawing, but rather for parsing. That is, it is up to the developer to turn the data structures returned by Simple KML into drawing code, be it for annotations in MapKit, constructs in an external mapping library, drawing paths on a UIImage, or otherwise.

Simple KML is basically an XML parser with smarts about KML. It presents a hierarchical view of KML data and can turn things like Simple KML color definitions into UIColor and text coordinates into CLLocation so that you don't have to.

Requirements

Simple KML has been designed & built for iOS 5.0 and greater. There's no particular reason it couldn't be adapted to Mac OS X; it just hasn't been done yet out of lack of necessity.

Simple KML is built for ARC.

Simple KML depends on TouchXML, an Objective-C library for DOM-based XML parsing based on libxml2, and Objective-Zip, a library for working with archive files, both of which are included in the download.

Features

  • Support for most of the base KML entities.

    Basic support for Object, Feature, Placemark, Container, Document, Folder, Geometry, Point, LineString, LinearRing, Polygon, StyleSelector, Style, SubStyle, BalloonStyle, ColorStyle, LineStyle, PolyStyle, IconStyle and ExtendedData.

  • Simple invocation.

    SimpleKML *myKML = [SimpleKML KMLWithContentsOfFile:@"/path/to/file.kml" error:&error]
    SimpleKML *myKML = [SimpleKML KMLWithContentsOfURL:[NSURL URLWithString:@"http://example.com/file.kml"] error:&error]

  • Support for KMZ archives.

    Currently searches for a top-level KML file in the archive and retrieves icon data for bundled IconStyle entities.

  • Cocoa-native behavior.

    Native types:

    SimpleKMLLineStyle *lineStyle = myPolygon.lineStyle; UIColor *lineColor = lineStyle.color;
    NSArray *polygonPoints = myPolygon.outerBoundary.coordinates; // CLLocation objects
    UIColor *textColor = myPlacemark.style.balloonStyle.textColor;
    UIImage *icon = myPlacemark.style.iconStyle.icon; // planned: automatically apply scale, heading, and parent style color

    Intelligent parsing:

    SimpleKMLStyle *inlineStyle = myPlacemark.inlineStyle; // within <Placemark>
    SimpleKMLStyle *sharedStyle = myPlacemark.sharedStyle; // common to <Document>; no need to reference <StyleUrl>
    SimpleKMLStyle *activeStyle = myPlacemark.style; // the inline style overrides the shared style

    SimpleKMLGeometry *geometry = myPlacemark.geometry; // <Point>, <Polygon>, <LineString>, <MultiGeometry>, etc.
    SimpleKMLPoint *point = myPlacemark.point; // shortcut if <Point> exists for <Placemark>

    Smart error handling:

    NSError *error;
    SimpleKML *myKML = [SimpleKML KMLWithContentsOfFile:@"invalid.kml" error:&error];
    if (error) { NSLog(@"%@", error); } // SimpleKMLParseError: Improperly formed KML (LinearRing has less than four coordinates)

    Debugging:

    gdb: po [mySimpleKMLObject source] // protected variable containing original XML source

    Hierarchies:

    SimpleKMLDocument *document = myPlacemark.document;
    NSArray *documentFeatures = document.features;

Usage

Be sure to clone recursively (git clone --recursive or git submodule update --init) in order to grab the dependent submodules Objective-Zip and TouchXML.

Include all of the Simple KML files in your Xcode project, as well as the files in the TouchXML and Objective-Zip subdirectories if you don't already use these in your project.

Per TouchXML's installation guide, add /usr/include/libxml2 to your "Header Search Paths" and -lxml2 to your "Other Linker Flags" since TouchXML depends on libxml2.

You'll also need to link against CoreLocation.framework and libz.dylib.

Plans, needs, bugs, etc.

If you find a bug or want to otherwise contribute, please fork the project on GitHub and contribute that way. In particular, I would like to start adding built-in testing with a library of accompanying KML test files to parse.

License

Copyright (c) 2010-2013 MapBox.

The Simple KML library should be accompanied by a LICENSE file. This file contains the license relevant to this distribution. If no license exists, please contact MapBox.

simple-kml's People

Contributors

gaving avatar incanus avatar itfrombit avatar jessecrocker avatar johnhaitas avatar rencire avatar tmcw avatar tscheepers avatar veerasrinivasan avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

simple-kml's Issues

non ARC compliant zip classes

The dev-arc branch compiles fine with the -fno-obj-arc compile flag set on the following files

FileInZipInfo.m
ZipFile.m
ZipReadStream.m
ZipWriteStream.m

However, I was wondering what the background is here, does a standard arc migration on these files (removal of release, dealloc, etc) continue to cause problems after the fact?

plz help

im follow the instrction , i add the touchxml library , but it still not recocnize identifiers as ZipFile , listfileinzip

iOS4: static analyzer warnings

Xcode 4.0 generates following static analyzer warnings when simpleXML is included in the project. The warnings are

  1. zip.c: Dead Store - Value stored to err is never read
  2. unzip.c: Dead store - value stored to lSeek is never read
  3. unzip.c: Dead store - value stored to lSeek is never read
  4. unzip.c: Dead store - value stored to err is never read

[LineString] Coordinates of LineString not supporting altitude

Hi Justin,

I was wondering, if it would be possible to extend the LineString class to support altitude values in the coordinates.

For reference I have added my code for testing altitude values:

- (id)initWithXMLNode:(CXMLNode *)node sourceURL:sourceURL error:(NSError **)error
{
  ******** SNIP ***********

 CLLocationDistance longitude = [[parts objectAtIndex:0] doubleValue];
 CLLocationDistance latitude  = [[parts objectAtIndex:1] doubleValue];
 CLLocationDistance altitude  = [[parts objectAtIndex:2] doubleValue];

 ******** SNIP/SNAP ***********                   

CLLocationCoordinate2D coordinate2D;
coordinate2D.latitude=latitude;
coordinate2D.longitude=longitude;


CLLocation* coordinate = [[CLLocation alloc] initWithCoordinate:coordinate2D 
altitude:altitude horizontalAccuracy:0 
 verticalAccuracy:0 
 timestamp:[NSDate date]];

********** SNAP  *************

}

Thanks,
Markus

Getting exception as “Collection was mutated while being enumerated”

Hi Guys,

I tried to check out a user pinpoint with polygon by looping through all the KMLs. the app always crash @ this point:

//create KML in hidden Mapview
-(void)loadKML:(NSMutableArray *)kmlNameArray
{
//dispatch_group_t group = dispatch_group_create();

//remove polygon and redraw again.
[NSThread detachNewThreadSelector: @selector(spinEnd) toTarget:self withObject:nil];

[mapView removeOverlays:mapView.overlays];
[inUserRangeArray removeAllObjects];
[inUserRangeArrayObjectIndex removeAllObjects];
[scrollview removeFromSuperview];
[pageControl removeFromSuperview];
[NSThread detachNewThreadSelector: @selector(spinBegin) toTarget:self withObject:nil];

NSArray *sysPaths = NSSearchPathForDirectoriesInDomains( NSDocumentDirectory, NSUserDomainMask, YES );
NSString *docDirectory = [sysPaths objectAtIndex:0];   


for (int e=0; e<[kmlNameArray count]; e++) 
{        
    //NSString *kmlNameStr = [kmlNameArray objectAtIndex:e];
    Frog *kmlID = [self.fs objectAtIndex:e];
    self.kmlID = [NSString stringWithFormat:@"%i",kmlID.fID];
    self.kmlIDObjectIndex = [NSString stringWithFormat:@"%i",e];

    NSLog(@"asasas %@",kmlIDObjectIndex);

    //NSLog(@"KML items %@", kmlNameStr);          
    //NSLog(@"KML ID %@", kmlID);
    //NSLog(@"KML file Path %@",[NSString stringWithFormat:@"%@/data/%@/%@", docDirectory,self.kmlID,[kmlNameArray objectAtIndex:e]]);


    SimpleKML *kml = [SimpleKML KMLWithContentsOfFile:[NSString stringWithFormat:@"%@/data/%@/%@", docDirectory,self.kmlID,[kmlNameArray objectAtIndex:e]]error:NULL];

    // look for a document feature in it per the KML spec


    //        dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{

    if (kml.feature && [kml.feature isKindOfClass:[SimpleKMLDocument class]])
    {// see if the document has features of its own
        for (SimpleKMLFeature *feature in ((SimpleKMLContainer *)kml.feature).features)
        {// otherwise, see if we have any placemark features with a polygon
            if ([feature isKindOfClass:[SimpleKMLPlacemark class]] && ((SimpleKMLPlacemark *)feature).polygon)
            {
                SimpleKMLPolygon *polygon = (SimpleKMLPolygon *)((SimpleKMLPlacemark *)feature).polygon;
                SimpleKMLLinearRing *outerRing = polygon.outerBoundary;
                //points[i], i = number of coordinates
                CLLocationCoordinate2D points[[outerRing.coordinates count]];
                NSUInteger i = 0;
                for (CLLocation *coordinate in outerRing.coordinates)
                { 
                    points[i++] = coordinate.coordinate;
                }
                // create a polygon annotation for it
                self.overlayPolygon = [MKPolygon polygonWithCoordinates:points count:[outerRing.coordinates count]];

                //crash here
                [mapView addOverlay:overlayPolygon];

                // zoom the map to the polygon bounds
                [mapView setVisibleMapRect:overlayPolygon.boundingMapRect animated:YES];

            }
        }
    } 
}

Calculate Area / Acres

Does this code support the calculation of Area / Acres from KML file? If not any idea how I could do this?

add support for ExtendedData elements

Hi:

I need this feature because i have a kml with this tags, a example:

<ExtendedData><SchemaData schemaUrl="#world_borders">
        <SimpleData name="Name">Antigua and Barbuda</SimpleData>
        <SimpleData name="FIPS">AC</SimpleData>
        <SimpleData name="ISO2">AG</SimpleData>
        <SimpleData name="ISO3">ATG</SimpleData>
        <SimpleData name="UN">28</SimpleData>
        <SimpleData name="AREA">44</SimpleData>
        <SimpleData name="POP2005">83039</SimpleData>
        <SimpleData name="REGION">19</SimpleData>
        <SimpleData name="SUBREGION">29</SimpleData>
        <SimpleData name="LON">-61.783</SimpleData>
        <SimpleData name="LAT">17.078</SimpleData>
</SchemaData></ExtendedData>

and here the google's reference:

https://developers.google.com/kml/documentation/kmlreference?hl=en#data

or how can implement this feature?

Thanks you

Bug and Memory leak in SimpleKMLLineString

Steps to reproduce:
Just load a KML with LineString in multigeometry/geometry structure and run it through profiler.

example linestring element in kml

-81.631893833368238,26.718140556285277
-81.632410101487054,26.718101432533082</LineString

Analysis:
Profiler reported memory leak and traced it down to bug in initWithXMLNode:sourceURL:error in SimpleKMLLineString class.

If your KML has LineString elements, it will leak as the above initializer returns nil after constructing coordinates array which will not get released if the initializer returns nil.

The line that extracts the coordinates from the child node using componentsSeparatedByString is not using whitespaceAndNewlineCharacterSet.

Here is the modified initWithXMLNode:sourceURL:error: for SimpleKMLLineString class.

  • (id)initWithXMLNode:(CXMLNode )node sourceURL:sourceURL error:(NSError *)error
    {
    self = [super initWithXMLNode:node sourceURL:sourceURL error:error];

    if (self != nil)
    {
    coordinates = nil;

    for (CXMLNode *child in [node children])
    {
        if ([[child name] isEqualToString:@"coordinates"])
        {
            NSMutableArray *parsedCoordinates = [NSMutableArray array];
    
            NSArray *coordinateStrings = [[child stringValue] componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; //To handle line tuple separated by newline
    
            for (NSString *coordinateString in coordinateStrings)
            {
                coordinateString = [coordinateString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
    
                if ([coordinateString length])
                {
                    // coordinates should not have whitespace
                    //
                    if ([[coordinateString componentsSeparatedByString:@" "] count] > 1)
                    {
                        NSDictionary *userInfo = [NSDictionary dictionaryWithObject:@"Improperly formed KML (LineString coordinates have whitespace)" 
                                                                             forKey:NSLocalizedFailureReasonErrorKey];
    
                        if (error)
                            *error = [NSError errorWithDomain:SimpleKMLErrorDomain code:SimpleKMLParseError userInfo:userInfo];
    
                        return nil;
                    }
    
                    NSArray *parts = [coordinateString componentsSeparatedByString:@","];
    
                    // there should be longitude, latitude, and optionally, altitude
                    //
                    if ([parts count] < 2 || [parts count] > 3)
                    {
                        NSDictionary *userInfo = [NSDictionary dictionaryWithObject:@"Improperly formed KML (Invalid number of LineString coordinates)" 
                                                                             forKey:NSLocalizedFailureReasonErrorKey];
    
                        if (error)
                            *error = [NSError errorWithDomain:SimpleKMLErrorDomain code:SimpleKMLParseError userInfo:userInfo];
    
                        return nil;
                    }
    
                    double longitude = [[parts objectAtIndex:0] doubleValue];
                    double latitude  = [[parts objectAtIndex:1] doubleValue];
    
                    // there should be valid values for latitude & longitude
                    //
                    if (longitude < -180 || longitude > 180 || latitude < -90 || latitude > 90)
                    {
                        NSDictionary *userInfo = [NSDictionary dictionaryWithObject:@"Improperly formed KML (Invalid LineString coordinates values)" 
                                                                             forKey:NSLocalizedFailureReasonErrorKey];
    
                        if (error)
                            *error = [NSError errorWithDomain:SimpleKMLErrorDomain code:SimpleKMLParseError userInfo:userInfo];
    
                        return nil;
                    }
    
                    CLLocation *coordinate = [[[CLLocation alloc] initWithLatitude:latitude longitude:longitude] autorelease];
    
                    [parsedCoordinates addObject:coordinate]; 
                }
            }
    
            coordinates = [[NSArray arrayWithArray:parsedCoordinates] retain];
    
            // there should be two or more coordinates
            //
            if ([coordinates count] < 2)
            {
                NSDictionary *userInfo = [NSDictionary dictionaryWithObject:@"Improperly formed KML (LineString has less than two coordinates)" 
                                                                     forKey:NSLocalizedFailureReasonErrorKey];
    
                if (error)
                    *error = [NSError errorWithDomain:SimpleKMLErrorDomain code:SimpleKMLParseError userInfo:userInfo];
    
                return nil;
            }
        }
    }
    
    if ( ! coordinates)
    {
        NSDictionary *userInfo = [NSDictionary dictionaryWithObject:@"Improperly formed KML (LineString has no coordinates)" 
                                                             forKey:NSLocalizedFailureReasonErrorKey];
    
        if (error)
            *error = [NSError errorWithDomain:SimpleKMLErrorDomain code:SimpleKMLParseError userInfo:userInfo];
    
        return nil;
    }
    

    }

    return self;
    }

Unable to parse KML file

Hi there,

I'm happily using Simple-KML in one of my pet projects for parsing a kmz file, but it appears that I'm having some difficulty parsing the .kml file from https://dl.dropboxusercontent.com/u/21695507/openplaques/london_20140202.kml.

When I step through the SimpleKML KMLWithContentsOfFile method, I can see that the stringified xml is easily loaded from my application's bundle.

However, when the following code is executed:

        CXMLDocument *document = [[CXMLDocument alloc] initWithXMLString:source
                                                                 options:0
                                                                   error:&parseError];

... it appears that the source is correct, but the resulting document is nil :( The parseError object is nil and the error object returned from the SimpleKML KMLWithContentsOfFile method is nil too. So, I'm not sure what the root cause of the issue is.

FWIW, I'm using the latest version of the library downloaded from github a few weeks ago.

I read the docs and you mentioned that you'd like to see unit tests added to the project for parsing problem files like this. I'd be happy to contribute, but would like your input. Would you be cool with XCTests? I've been using Kiwi recently and like it, but don't have a strong preference.

Thanks again for the awesome library,

Sean

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.