I have an xml based application. I have written all the code to do xml parsing but the main problem is my parser does not gets into the didStartElement
method. It skips the didStartElement
and foundCharacters
method and directly gets into the didEndElement
and returns count of 0 in my array. What may be the problem? I have compared with the proper elements of xml.
This is my api method; through this method I get xml file.
#开发者_JAVA百科import <Foundation/Foundation.h>
@interface api : NSObject {
NSError *error;
NSURLResponse *response;
NSData *dataReply;
}
@property (nonatomic, retain)NSData *dataReply;
-(NSData *)getBusXMLAtStop:(NSString*)stopnumber;
@end
#import "api.h"
@implementation api
@synthesize dataReply;
//@synthesize stringReply;
-(NSData *)getBusXMLAtStop:(NSString*)stopnumber
{
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:
[NSURL URLWithString: [NSString stringWithFormat:@"http://www.google.com/ig/api?weather=,,,50500000,30500000",stopnumber]]];
[request setHTTPMethod: @"GET"];
dataReply = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSLog(@"%@",dataReply);
return dataReply;
}
-(void)dealloc
{
[super dealloc];
[dataReply release];
}
@end
This is my parser class where i am parsing each and every element of xml:
#import "TWeatherElement.h"//this is the class where the elements are Created
#import <Foundation/Foundation.h>
@interface TWeatherParser : NSObject<NSXMLParserDelegate>
{
NSMutableArray *mParserArray;//this is the array i have in the parser class to hold the elements
NSXMLParser *mXmlParser;
NSMutableString *mCurrentElement;
BOOL elementFound;
TWeatherElement *mWeatherobj;
}
@property (nonatomic, retain) NSMutableString *currentElement;
@property (nonatomic, retain)NSMutableArray *mParserArray;
@property (nonatomic, retain) TWeatherElement *weatherobj;
-(void)getInitialiseWithData:(NSData *)inData;
@end
#import "TWeatherParser.h"
#import "JourneyAppDelegate.h"
#import "api.h"
@implementation TWeatherParser
@synthesize weatherobj = mWeatherobj;
@synthesize currentElement = mCurrentElement;
@synthesize mParserArray;
-(void)getInitialiseWithData:(NSData *)inData
{
NSXMLParser *parser = [[NSXMLParser alloc] initWithData:inData];
[parser setDelegate:self];
[parser setShouldProcessNamespaces:NO];
[parser setShouldReportNamespacePrefixes:NO];
[parser setShouldResolveExternalEntities:NO];
[parser parse];
[parser release];
}
-(void)parser:(NSXMLParser *)parser didStartElement:(NSString*) elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString*)qualifiedName attribute:(NSDictionary*)attributeDict
{
if (nil!= qualifiedName)
{
elementName = qualifiedName;
}
if ([elementName isEqualToString:@"weather"])
{
[mParserArray addObject:elementName];
self.weatherobj = [[TWeatherElement alloc]init];
}
else if([elementName isEqualToString:@"current_date_time"]||
[elementName isEqualToString:@"condition"]||
[elementName isEqualToString:@"humidity"]||
[elementName isEqualToString:@"icon d"]||
[elementName isEqualToString:@"wind_condition"]||
[elementName isEqualToString:@"low"]||
[elementName isEqualToString:@"high"])
{
self.currentElement = [NSMutableString string];
}
else
{
self.currentElement = nil;
}
}
-(void)parser:(NSXMLParser*)parser foundCharacters:(NSString*)string
{
if (nil!= self.currentElement)
{
[self.currentElement appendString:string];
}
}
-(void)parser:(NSXMLParser *)parser didEndElement:(NSString*)elementName namespaceURI:(NSString*)namespaceURI qualifiedName:(NSString*)qName
{
if (nil != qName)
{
elementName = qName;
}
if ([elementName isEqualToString:@"current_date_time"])
{
self.weatherobj.currentdate = self.currentElement;
}
else if ([elementName isEqualToString:@"condition"])
{
self.weatherobj.conditionname = self.currentElement;
}
else if ([elementName isEqualToString:@"humidity"])
{
self.weatherobj.humidity = self.currentElement;
}
else if ([elementName isEqualToString:@"icon"])
{
self.weatherobj.icon = self.currentElement;
}
else if ([elementName isEqualToString:@"wind_condition"])
{
self.weatherobj.wind = self.currentElement;
}
else if ([elementName isEqualToString:@"low"])
{
self.weatherobj.mintemp = self.currentElement;
}
else if ([elementName isEqualToString:@"high"])
{
self.weatherobj.maxtemp = self.currentElement;
}
else if ([elementName isEqualToString:@"weather"])
{
[mParserArray addObject:self.weatherobj];
NSLog(@"mDataArray count = %d",[mParserArray count]);
[self.weatherobj release];
}
}
-(void)dealloc
{
self.weatherobj = nil;
self.currentElement = nil;
[super dealloc];
}
@end
This is the tableviewcontroller class where I want to display the values fetched from the xml on the tableviewcell
#import <UIKit/UIKit.h>
#import "TWeatherParser.h"
@class TWeatherParser;
@interface TWeatherController : UITableViewController {
UITableView *mTableView;
NSMutableArray *mImage;
NSMutableArray *weatherarray;//this is the array that has been created in this class.
TWeatherParser *weather;
}
@property (nonatomic, retain) IBOutlet UITableView *mTableView;
@end
//
// TWeatherController.m
// Journey
//
// Created by raji.nair on 5/3/11.
// Copyright 2011 __MyCompanyName__. All rights reserved.
//
#import "TWeatherController.h"
#import "TWeatherCell.h"
#import "TWeatherElement.h"
#import "TWeatherParser.h"
#import "api.h"
@implementation TWeatherController
@synthesize mTableView;
#pragma mark -
#pragma mark Initialization
- (id)initWithStyle:(UITableViewStyle)style {
// Override initWithStyle: if you create the controller programmatically and want to perform customization that is not appropriate for viewDidLoad.
style = UITableViewStyleGrouped;
if (self = [super initWithStyle:style]) {
}
return self;
}
#pragma mark -
#pragma mark View lifecycle
/*
- (void)viewDidLoad {
[super viewDidLoad];
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
}
*/
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
api *ap = [[api alloc]init];
NSData *aData = [ap getBusXMLAtStop:@"1"];
NSString *str = [[NSString alloc] initWithData:aData encoding:NSUTF8StringEncoding];
//NSInteger value = [str intValue];
if (str!= NULL)
{
NSLog(@"this is success %@",ap.dataReply);
TWeatherParser *parser = [[TWeatherParser alloc]init];
[parser getInitialiseWithData:ap.dataReply];
[parser release];
}
else
{
UIAlertView *alertview = [[UIAlertView alloc]initWithTitle:@"Alert" message:@"cannot fetch" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
[alertview show];
[alertview release];
}
[ap release];
}
#pragma mark -
#pragma mark Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// Return the number of sections.
return 2;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
**return [weather.mParserArray count];**.//Here i am having a doubt that which array should i count over here
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Cell";
TWeatherCell *cell =(TWeatherCell *) [mTableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[TWeatherCell alloc] initWithStyle:UITableViewStyleGrouped reuseIdentifier:CellIdentifier] autorelease];
}
TWeatherElement *newobj = [weather.mParserArray objectAtIndex:indexPath.row];
if ([newobj.icon isEqualToString:@"http://\n"])
{
cell.weatherimage.image = [UIImage imageNamed:@"listIcon-H.png"];
}
else {
NSData *imageData = [[NSData alloc]initWithContentsOfURL:[NSURL URLWithString:newobj.icon]];
cell.weatherimage.image = [UIImage imageWithData:imageData];
[imageData release];
}
cell.reportdate.text = newobj.currentdate;
cell.conditionname.text = newobj.conditionname;
cell.twotemp.text = [NSString stringWithFormat:@"Temp:%@/%@",newobj.mintemp,newobj.maxtemp];
cell.twodirection.text = newobj.wind;
cell.humidity.text = newobj.humidity;
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
// Configure the cell...
return cell;
}
#pragma mark -
#pragma mark Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
// Navigation logic may go here. Create and push another view controller.
/*
<#DetailViewController#> *detailViewController = [[<#DetailViewController#> alloc] initWithNibName:@"<#Nib name#>" bundle:nil];
// ...
// Pass the selected object to the new view controller.
[self.navigationController pushViewController:detailViewController animated:YES];
[detailViewController release];
*/
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *) indexPath
{
return 100.0;
}
#pragma mark -
#pragma mark Memory management
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Relinquish ownership any cached data, images, etc. that aren't in use.
}
- (void)viewDidUnload {
// Relinquish ownership of anything that can be recreated in viewDidLoad or on demand.
// For example: self.myOutlet = nil;
}
- (void)dealloc {
[super dealloc];
}
@end
XML File;
<?xml version="1.0"?><xml_api_reply version="1"><weather module_id="0" tab_id="0" mobile_row="0" mobile_zipped="1" row="0" section="0" ><forecast_information><city data=""/><postal_code data=""/><latitude_e6 data="50500000"/><longitude_e6 data="30500000"/><forecast_date data="2011-05-26"/><current_date_time data="2011-05-26 04:00:00 +0000"/><unit_system data="US"/></forecast_information><current_conditions><condition data="Clear"/><temp_f data="52"/><temp_c data="11"/><humidity data="Humidity: 62%"/><icon data="/ig/images/weather/sunny.gif"/><wind_condition data="Wind: NW at 9 mph"/></current_conditions><forecast_conditions><day_of_week data="Thu"/><low data="48"/><high data="68"/><icon data="/ig/images/weather/mostly_sunny.gif"/><condition data="Mostly Sunny"/></forecast_conditions><forecast_conditions><day_of_week data="Fri"/><low data="52"/><high data="75"/><icon data="/ig/images/weather/mostly_sunny.gif"/><condition data="Mostly Sunny"/></forecast_conditions><forecast_conditions><day_of_week data="Sat"/><low data="55"/><high data="81"/><icon data="/ig/images/weather/mostly_sunny.gif"/><condition data="Mostly Sunny"/></forecast_conditions><forecast_conditions><day_of_week data="Sun"/><low data="55"/><high data="86"/><icon data="/ig/images/weather/mostly_sunny.gif"/><condition data="Partly Sunny"/></forecast_conditions></weather></xml_api_reply>
Check These thinks in your coding
[xmlParser setDelegate:self];
[xmlParser setShouldProcessNamespaces:NO];
[xmlParser setShouldReportNamespacePrefixes:NO];
[xmlParser setShouldResolveExternalEntities:NO];
[xmlParser parse];
If you've copy/pasted your code from your project, the reason, why ...didStartElement:...
isn't called, is a minor typo:
// Your method:
-(void)parser:(NSXMLParser *)parser didStartElement:(NSString*) elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString*)qualifiedName attribute:(NSDictionary*)attributeDict
// NSXMLParserDelegate's method:
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict;
Read: You are missing an "s" on the last part of the selector.
If you've copied the selector from the docs, please go and file a bug — this type of stuff has bitten me quite a few times, too :-(
Update
In order to process attributes, you have to work with the dictionary you get passed in parser:didStartElement:…attributes:
. (See Handling Elements in the "Event-Driven XML Programming Guide" for further reference.)
精彩评论