Re: NSXMLParser question about duplicate nodes
Re: NSXMLParser question about duplicate nodes
- Subject: Re: NSXMLParser question about duplicate nodes
- From: Peter Blazejewicz <email@hidden>
- Date: Thu, 7 Jan 2010 00:36:01 +0100
Hi Eric,
On Wed, Jan 6, 2010 at 9:46 PM, Philip Vallone
<email@hidden> wrote:
> Hi.
>
> I would recommend LibXML. This post is excellent and the the author created an Objective C Wrapper.
>
> http://cocoawithlove.com/2008/10/using-libxml2-for-parsing-and-xpath.html
>
> Regards,
>
I can see you have already got two recommendation for using other lib
and wrapper and some for fixing your NSXMLParser delegate issue,
Answering your original question:
#1
Yahoo! api will always return only two days in forecast: day for which
current forecast was released (not necessary today locally, yes?) and
next day:
http://developer.yahoo.com/weather/#item
#2
example of (nearly) full implementation of
NSURLConnection+delegate/NSXMLParser+delegate for your specific use
case could be written as below sample (please read from top to bottom)
and could be started from e.g. UI controller method (main thread).
Please note that NSXMLParser implementation is very, very simple in
your specific use case (parsing only two days forecast from received
feed):
- (void)fetchRecentForecastForCode:(NSString *)weatherCode
{
static NSString *feedURLString =
@"http://weather.yahooapis.com/forecastrss?w=%@&u=c";
NSURL *feedURL = [NSURL URLWithString:[NSString
stringWithFormat:feedURLString, weatherCode]];
NSURLRequest *feedRequest = [NSURLRequest requestWithURL:feedURL];
NSURLConnection *feedConnection = [[[NSURLConnection alloc]
initWithRequest:feedRequest delegate:self] autorelease];
// property for NSURLConnection reference
self.weatherFeedConnection = feedConnection;
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
}
- (void)connection:(NSURLConnection *)connection
didReceiveResponse:(NSURLResponse *)response
{
// property for accumulated data from request
self.weatherFeedData = [[[NSMutableData alloc] initWithLength:0]
autorelease];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[self.weatherFeedData appendData:data];
}
- (void)connection:(NSURLConnection *)connection
didFailWithError:(NSError *)error
{
NSLog(@"%s %@", __FUNCTION__, error);
self.weatherFeedConnection = nil;
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
self.weatherFeedConnection = nil;
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
// now start new background thread to parse received data using NSXMLParser
[self performSelectorInBackground:@selector(parseWeatherFeedXML:)
withObject:self.weatherFeedData];
self.weatherFeedData = nil;
}
//
- (void)parseWeatherFeedXML:(NSData *)feedData
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// property for counter of parsed days (max two)
self.parsedForecastDayCounter = 0;
// we will add parsed days (object) to array property
self.parsedDays = [NSMutableArray arrayWithCapacity:2];
NSXMLParser *parser = [[NSXMLParser alloc] initWithData:feedData];
parser.delegate = self;
[parser setShouldProcessNamespaces:YES];
[parser parse];
// after parser ends we check what we got
if(self.parsedForecastDayCounter > 0)
{
// and update UI in main (UI) thread
[self performSelectorOnMainThread:@selector(forecastParsedForDays:)
withObject:self.parsedDays waitUntilDone:NO];
}
self.parsedDays = nil;
[parser release]; parser = nil;
[pool drain];
}
//
static NSString * const kForecastElementName = @"yweather:forecast";
static NSString * const kForecastElementDayKey = @"day";
static NSString * const kForecastElementDateKey = @"date";
static NSString * const kForecastElementLowKey = @"low";
static NSString * const kForecastElementHightKey = @"high";
static NSString * const kForecastElementTextKey = @"text";
static NSString * const kForecastElementCodeKey = @"code";
static const const NSUInteger kMaximumNumberOfDaysToParse = 2;
//
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString
*)elementName namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName attributes:(NSDictionary
*)attributeDict
{
if(qName && ([qName isEqualToString:kForecastElementName]))
{
NSLog(@"%s %@ (%@)", __FUNCTION__, elementName, qName);
NSMutableDictionary *forecast = [[NSMutableDictionary alloc] init];
[forecast setValue:[attributeDict
valueForKey:kForecastElementDayKey] forKey:kForecastElementDayKey];
[forecast setValue:[attributeDict
valueForKey:kForecastElementDateKey] forKey:kForecastElementDateKey];
[forecast setValue:[attributeDict
valueForKey:kForecastElementLowKey] forKey:kForecastElementLowKey];
[forecast setValue:[attributeDict
valueForKey:kForecastElementHightKey]
forKey:kForecastElementHightKey];
[forecast setValue:[attributeDict
valueForKey:kForecastElementTextKey] forKey:kForecastElementTextKey];
[forecast setValue:[attributeDict
valueForKey:kForecastElementCodeKey] forKey:kForecastElementCodeKey];
[self.parsedDays addObject:forecast];
[forecast release]; forecast = nil;
self.parsedForecastDayCounter++;
}
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString
*)elementName namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName
{
if(qName && ([qName isEqualToString:kForecastElementName]))
{
// we are done - no reason to parse further after 2 days offered by api
if(self.parsedForecastDayCounter >= kMaximumNumberOfDaysToParse)
{
[parser abortParsing];
return;
}
}
}
// called from background thread after parsing is done
- (void)forecastParsedForDays:(NSArray *)parsedDays
{
NSMutableString *outputStr = [[NSMutableString alloc] initWithString:@""];
NSObject *forecast = nil;
for (forecast in parsedDays) {
[outputStr appendString:[NSString stringWithFormat:@"%@:
%@\n", kForecastElementDayKey, [forecast
valueForKey:kForecastElementDayKey]]];
[outputStr appendString:[NSString stringWithFormat:@"%@:
%@\n", kForecastElementDateKey, [forecast
valueForKey:kForecastElementDateKey]]];
[outputStr appendString:[NSString stringWithFormat:@"%@:
%@\n", kForecastElementLowKey, [forecast
valueForKey:kForecastElementLowKey]]];
[outputStr appendString:[NSString stringWithFormat:@"%@:
%@\n", kForecastElementHightKey, [forecast
valueForKey:kForecastElementHightKey]]];
[outputStr appendString:[NSString stringWithFormat:@"%@:
%@\n", kForecastElementTextKey, [forecast
valueForKey:kForecastElementTextKey]]];
[outputStr appendString:[NSString stringWithFormat:@"%@:
%@\n", kForecastElementCodeKey, [forecast
valueForKey:kForecastElementCodeKey]]];
}
self.textView.text = outputStr;
[outputStr release]; outputStr = nil;
}
with regards from reader of your books,
Peter Blazejewicz
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden