-
Notifications
You must be signed in to change notification settings - Fork 1
/
BSGoogleV2KmlParser.m
204 lines (165 loc) · 5.74 KB
/
BSGoogleV2KmlParser.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
//
// Created by Björn Sållarp on 2010-03-13.
// NO Copyright 2010 MightyLittle Industries. NO rights reserved.
//
// Use this code any way you like. If you do like it, please
// link to my blog and/or write a friendly comment. Thank you!
//
// Read my blog @ http://blog.sallarp.com
//
/**
Kml Parser for Googles geocoding service version 2. Find out more @ Google:
http://code.google.com/apis/maps/documentation/geocoding/index.html
**/
#import "BSGoogleV2KmlParser.h"
@implementation BSGoogleV2KmlParser
@synthesize name, statusCode;
@synthesize placemarks = placemarkArray;
- (BOOL)parseXMLFileAtURL:(NSURL *)URL parseError:(NSError **)error
{
BOOL successfull = TRUE;
// Create XML parser
NSXMLParser *parser = [[NSXMLParser alloc] initWithContentsOfURL:URL];
// Set self as the delegate of the parser so that it will receive the parser delegate methods callbacks.
[parser setDelegate:self];
[parser setShouldProcessNamespaces:NO];
[parser setShouldReportNamespacePrefixes:NO];
[parser setShouldResolveExternalEntities:NO];
// Start parsing
[parser parse];
NSError *parseError = [parser parserError];
if (parseError && error) {
*error = parseError;
successfull = FALSE;
}
[parser release];
return successfull;
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName
attributes:(NSDictionary *)attributeDict
{
if (qName) {
elementName = qName;
}
// The response could contain multiple placemarks
if([elementName isEqualToString:@"Placemark"])
{
// Set up an array to hold placemarks
if(placemarkArray == nil)
{
placemarkArray = [[NSMutableArray alloc] init];
}
// Create a new placemark object to fill with information
currentPlacemark = [[BSKmlResult alloc] init];
}
// These are the elements we read information from.
if([elementName isEqualToString:@"code"] || [elementName isEqualToString:@"name"] || [elementName isEqualToString:@"address"]
|| [elementName isEqualToString:@"CountryNameCode"] || [elementName isEqualToString:@"CountryName"]
|| [elementName isEqualToString:@"SubAdministrativeAreaName"] || [elementName isEqualToString:@"LocalityName"]
|| [elementName isEqualToString:@"coordinates"])
{
// Create a mutable string to hold the contents of the elements.
// The content is collected in parser:foundCharacters:.
if(contentsOfCurrentProperty == nil)
{
contentsOfCurrentProperty = [NSMutableString string];
}
else
{
[contentsOfCurrentProperty setString:@""];
}
}
// Unlike most other information the LatLonBox and AddressDetails elements has interesting data in attributes
else if([elementName isEqualToString:@"LatLonBox"])
{
currentPlacemark.viewportSouthWestLat = [[attributeDict valueForKey:@"south"] floatValue];
currentPlacemark.viewportSouthWestLon = [[attributeDict valueForKey:@"west"] floatValue];
currentPlacemark.viewportNorthEastLat = [[attributeDict valueForKey:@"north"] floatValue];
currentPlacemark.viewportNorthEastLon = [[attributeDict valueForKey:@"east"] floatValue];
}
else if([elementName isEqualToString:@"AddressDetails"])
{
currentPlacemark.accuracy = [[attributeDict valueForKey:@"Accuracy"] intValue];
}
else
{
// If we're not interested in the element we set the variable used
// to collect information to nil.
contentsOfCurrentProperty = nil;
}
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName
{
if (qName) {
elementName = qName;
}
// If we reach the end of a placemark element we add it to our array
if([elementName isEqualToString:@"Placemark"])
{
if(currentPlacemark != nil)
{
[placemarkArray addObject:currentPlacemark];
[currentPlacemark release];
currentPlacemark = nil;
}
}
// If contentsOfCurrentProperty is nil we're not interested in the
// collected data
if(contentsOfCurrentProperty == nil)
return;
NSString* elementValue = [[NSString alloc] initWithString:contentsOfCurrentProperty];
if ([elementName isEqualToString:@"name"]) {
self.name = elementValue;
}
else if ([elementName isEqualToString:@"code"]) {
statusCode = [elementValue intValue];
}
if ([elementName isEqualToString:@"address"]) {
currentPlacemark.address = elementValue;
}
if ([elementName isEqualToString:@"CountryNameCode"]) {
currentPlacemark.countryNameCode = elementValue;
}
if ([elementName isEqualToString:@"CountryName"]) {
currentPlacemark.countryName = elementValue;
}
if ([elementName isEqualToString:@"SubAdministrativeAreaName"]) {
currentPlacemark.subAdministrativeAreaName = elementValue;
}
if ([elementName isEqualToString:@"LocalityName"]) {
currentPlacemark.localityName = elementValue;
}
if ([elementName isEqualToString:@"coordinates"]) {
// Coordinates are stored in a comma separated string.
NSArray *chunks = [elementValue componentsSeparatedByString: @","];
currentPlacemark.longitude = [[chunks objectAtIndex:0] floatValue];
currentPlacemark.latitude = [[chunks objectAtIndex:1] floatValue];
}
[elementValue release];
contentsOfCurrentProperty = nil;
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
if (contentsOfCurrentProperty) {
// If the current element is one whose content we care about, append 'string'
// to the property that holds the content of the current element.
[contentsOfCurrentProperty appendString:string];
}
}
-(void)dealloc
{
if(contentsOfCurrentProperty != nil) {
[contentsOfCurrentProperty release];
}
if(placemarkArray != nil)
{
[placemarkArray release];
}
[name release];
[super dealloc];
}
@end