This is the XML data:
<Categorys>
<Category>
<categoryId>25</categoryId>
<categoryName>My Photos</categoryName>
<categoryDescription>Description</categoryDescription>
<categoryIconPath>7.jpg</categoryIconPath>
<userId>2</userId>
<categoryStatus>ON</categoryStatus>
<publicPrivate>Private</publicPrivate>
</Category>
......more categories
<Categorys>
Here I want to get the <categoryName> values into my NSMutableArray categList.
The code I have used is:
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qualifiedName
attributes:(NSDictionary*)attributeDict {
if ( [elementName isEqualToString:#"categList"]) {
// addresses is an NSMutableArray instance variable
if (!categList)
categList = [[NSMutableArray alloc] init];
return;
}
NSLog(#"StartedElement %#", elementName);
element = [NSMutableString string];
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
if(element == nil)
element = [[NSMutableString alloc] init];
[element appendString:string];
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName {
NSLog(#"Found an element named: %# with a value of: %#", elementName, element);
if ([elementName isEqualToString:#"categoryName"]) {
NSLog(#"\n\n\nfound::::::::::::::: %#", element);
category = element;
NSLog(#"category:::: %#", category);
}
[categList addObject:element];
NSLog(#"categList*************** %#", categList);
}
But I am not getting the category names in my NSMutableArray categList:
Whats wrong in my code? :(
Thanks
Hey You can use XMLReader but it will return NSDictionary.
The Following code demo for XMLReader to get NSDictionary.
import XMLReader in your file.
#import "XMLReader.h"
Then use following method to get NSDictionary. Where you have to pass your XML as NSString
.
NSDictionary* xmlDict = [XMLReader dictionaryForXMLString:theXML error:&er];
If you want to use GDataXMLParser you can use following code that is working fine
First Impost GDataXMLParser library file then write vbe
-(void)XMLParsing
{
GdataParser *parser = [[GdataParser alloc] init];
NSString* urlString = #"YOURURL";
NSURL *url = [[NSURL alloc] initWithString:urlString];
[parser downloadAndParse:url withRootTag:#"Category" withTags:[NSDictionary dictionaryWithObjectsAndKeys:#"categoryId",#"categoryId",#"categoryName",#"categoryName",#"categoryDescription",#"categoryDescription",#"categoryIconPath",#"categoryIconPath",#"userId",#"userId",#"categoryStatus",#"categoryStatus",#"publicPrivate",#"publicPrivate",nil]
sel:#selector(finishGetDataSF:)
andHandler:self];
[urlSR release];
[parser release];
}
-(void)getDate:(NSDictionary*)dict
{
NSLog(#"Data from XML file == %#",dict);
NSArray* arrayTemp = [dict copy];
}
here i have parsing of you r Application its working very fine pls check it make a category object orientation class and use it.
-(void)loaddatafromxml
{
NSString *ur=[NSString stringWithFormat:#"Enter your url"];
NSURL *url=[NSURL URLWithString:ur];
NSMutableURLRequest *req=[NSMutableURLRequest requestWithURL:url];
conn=[[NSURLConnection alloc]initWithRequest:req delegate:self];
if(conn)
webdata=[[NSMutableData data]retain];
}
-(void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[webdata appendData:data];
}
-(void) connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
[webdata setLength:0];
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
categaryArry=[[NSMutableArray alloc]init];
NSString *thexml=[[NSString alloc] initWithBytes:[webdata mutableBytes] length:[webdata length] encoding:NSASCIIStringEncoding];
NSArray *arr=[thexml componentsSeparatedByString:#"<Category>"];
for(int i=1;i<[arr count];i++)
{
categList *object = [[categList alloc] init];
NSString *str=[arr objectAtIndex:i];
NSArray *arr=[str componentsSeparatedByString:#"<categoryId>"];
NSString *data=[arr objectAtIndex:1];
NSRange ranfrom=[data rangeOfString:#"</categoryId>"];
object.catid=[data substringToIndex:ranfrom.location];
arr=[str componentsSeparatedByString:#"<categoryName>"];
data=[arr objectAtIndex:1];
ranfrom=[data rangeOfString:#"</categoryName>"];
object.catname=[data substringToIndex:ranfrom.location];
arr=[str componentsSeparatedByString:#"<categoryDescription>"];
data=[arr objectAtIndex:1];
ranfrom=[data rangeOfString:#"</categoryDescription>"];
object.catdesc=[data substringToIndex:ranfrom.location];
arr=[str componentsSeparatedByString:#"<categoryIconPath>"];
data=[arr objectAtIndex:1];
ranfrom=[data rangeOfString:#"</categoryIconPath>"];
object.caticon=[data substringToIndex:ranfrom.location];
arr=[str componentsSeparatedByString:#"<userId>"];
data=[arr objectAtIndex:1];
ranfrom=[data rangeOfString:#"</userId>"];
object.userid=[data substringToIndex:ranfrom.location];
arr=[str componentsSeparatedByString:#"<categoryStatus>"];
data=[arr objectAtIndex:1];
ranfrom=[data rangeOfString:#"</categoryStatus>"];
object.catstatus=[data substringToIndex:ranfrom.location];
arr=[str componentsSeparatedByString:#"<publicPrivate>"];
data=[arr objectAtIndex:1];
ranfrom=[data rangeOfString:#"</publicPrivate>"];
object.publicpriv=[data substringToIndex:ranfrom.location];
[categaryArry addObject:object];
}
[self.table_data reloadData];
[thexml release];
[connection release];
}
and call the loaddatafrm xml function as [self loaddatafromxml]; its working nice try it .
Thanks
You use if ( [elementName isEqualToString:#"categList"])... but I can't find categList name in you XML sample. Check please - this can be an issue.
Related
I am new in xml parsing.I am totaly cofused how many methods we should have to require for xml parsing and what does use of that method.I want to send input to the webservied and by use of xml parsing i want to display result in my text field.
See this questions for resources on how to pick an XML parser for your iOS application:
Choosing the right IOS XML parser
I choose TouchXML for my projects. It is a DOM parser and has XPath support:
https://github.com/TouchCode/TouchXML
You should use the following methods:
- (void)parseXMLFileAtURL:(NSString *)URL { //own method from me, URL could be local file or internet website
itemsOfFeed = [[NSMutableArray alloc] init];
NSURL *xmlURL = [NSURL URLWithString:URL];
feedParser = [[NSXMLParser alloc] initWithContentsOfURL:xmlURL];
[feedParser setDelegate:self];
[feedParser setShouldProcessNamespaces:NO];
[feedParser setShouldReportNamespacePrefixes:NO];
[feedParser setShouldResolveExternalEntities:NO];
[feedParser parse];
}
- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError {
//in case of an error
}
- (void)parserDidStartDocument:(NSXMLParser *)parser {
// start to parse xml
}
-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
feedElement = [elementName copy];
if([elementName isEqualToString:#"item"]) { //main xml tag
item = [[NSMutableDictionary alloc] init];
feedTitle = [[NSMutableString alloc] init];
feedDate = [[NSMutableString alloc] init];
feedText = [[NSMutableString alloc] init];
feedLink = [[NSMutableString alloc] init];
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
if([feedElement isEqualToString:#"title"]) {
[feedTitle appendString:string];
} else if([feedElement isEqualToString:#"link"]) { // some examples of tags
[feedLink appendString:string];
} else if([feedElement isEqualToString:#"content:encoded"]) {
[feedText appendString:string];
} else if([feedElement isEqualToString:#"pubDate"]) {
[feedDate appendString:string];
}
}
- (void) parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
if([elementName isEqualToString:#"item"]) {
[item setObject:feedTitle forKey:#"title"];
[item setObject:feedDate forKey:#"date"];
[item setObject:feedText forKey:#"text"];
[item setObject:feedLink forKey:#"link"];
[itemsOfFeed addObject:item];
}
}
- (void)parserDidEndDocument:(NSXMLParser *)parser {
[self.myTableView reloadData]; // for example reload table view
[self writeArrayToFile]; //or write to a local property list
}
in your header file:
NSMutableArray *itemsOfFeed;
NSXMLParser *feedParser;
NSMutableDictionary *item;
NSMutableString *feedElement;
NSMutableString *feedTitle, feedDate, feedText, feedLink; //strings of your tags
Then you have:
NSArray
NSDictionary
object a
object b
object c
Just access 'object a' and put it in your text field
hopefully this code example helps you
Here is the very helpful tutorial.
http://www.edumobile.org/iphone/iphone-programming-tutorials/parsing-an-xml-file/
Hi I would personally prefer to use NSXMLParser.
Write your own code which uses NSXMLParserDelegate methods implementation.
But still there are some third party libraries available. Here is a nice example to compare how all those parser differs from each other and also having nice explanation. Code is also available over there.
Hope this will be helpful to you.
-Mrunal
i have a demo app for parsing static XML to UITableView, I think this one will surely will help you.
Availiable third party libraries available below, depend on developer choice this, which is best?
NSXMLParser
libxml2
TBXMLParser
TouchXMLParser
KissXMLParser
TinyXMLParser
GDataXMLParser
And you can also get more information from this great tutorial link
http://www.raywenderlich.com/553/how-to-chose-the-best-xml-parser-for-your-iphone-project
Try this:
XMLReader.h
//
// XMLReader.h
//
//
#import <Foundation/Foundation.h>
#interface XMLReader : NSObject <NSXMLParserDelegate>
{
NSMutableArray *dictionaryStack;
NSMutableString *textInProgress;
NSError *errorPointer;
}
+ (NSDictionary *)dictionaryForPath:(NSString *)path error:(NSError **)errorPointer;
+ (NSDictionary *)dictionaryForXMLData:(NSData *)data error:(NSError **)errorPointer;
+ (NSDictionary *)dictionaryForXMLString:(NSString *)string error:(NSError **)errorPointer;
#end
XMLReader.m
//
// XMLReader.m
//
#import "XMLReader.h"
//NSString *const kXMLReaderTextNodeKey = #"text";
#interface XMLReader (Internal)
- (id)initWithError:(NSError **)error;
- (NSDictionary *)objectWithData:(NSData *)data;
#end
#implementation XMLReader
#pragma mark -
#pragma mark Public methods
+ (NSDictionary *)dictionaryForPath:(NSString *)path error:(NSError **)errorPointer
{
NSString *fullpath = [[NSBundle bundleForClass:self] pathForResource:path ofType:#"xml"];
NSData *data = [[NSFileManager defaultManager] contentsAtPath:fullpath];
NSDictionary *rootDictionary = [XMLReader dictionaryForXMLData:data error:errorPointer];
return rootDictionary;
}
+ (NSDictionary *)dictionaryForXMLData:(NSData *)data error:(NSError **)error
{
XMLReader *reader = [[XMLReader alloc] initWithError:error];
NSDictionary *rootDictionary = [reader objectWithData:data];
[reader release];
return rootDictionary;
}
+ (NSDictionary *)dictionaryForXMLString:(NSString *)string error:(NSError **)error
{
NSArray* lines = [string componentsSeparatedByString:#"\n"];
NSMutableString* strData = [NSMutableString stringWithString:#""];
for (int i = 0; i < [lines count]; i++)
{
[strData appendString:[[lines objectAtIndex:i] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]];
}
NSData *data = [strData dataUsingEncoding:NSUTF8StringEncoding];
return [XMLReader dictionaryForXMLData:data error:error];
}
#pragma mark -
#pragma mark Parsing
- (id)initWithError:(NSError **)error
{
if ((self = [super init]))
{
errorPointer = *error;
}
return self;
}
- (void)dealloc
{
[dictionaryStack release];
[textInProgress release];
[super dealloc];
}
- (NSDictionary *)objectWithData:(NSData *)data
{
// Clear out any old data
[dictionaryStack release];
[textInProgress release];
dictionaryStack = [[NSMutableArray alloc] init];
textInProgress = [[NSMutableString alloc] init];
// Initialize the stack with a fresh dictionary
[dictionaryStack addObject:[NSMutableDictionary dictionary]];
// Parse the XML
NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];
parser.delegate = self;
BOOL success = [parser parse];
[parser release];
// Return the stack's root dictionary on success
if (success){
NSDictionary *resultDict = [dictionaryStack objectAtIndex:0];
return resultDict;
}
return nil;
}
# pragma mark
# pragma mark - NSXMLParserDelegate methods
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
// Get the dictionary for the current level in the stack
NSMutableDictionary *parentDict = [dictionaryStack lastObject];
// Create the child dictionary for the new element
NSMutableDictionary *childDict = [NSMutableDictionary dictionary];
// Initialize child dictionary with the attributes, prefixed with '#'
for (NSString *key in attributeDict) {
[childDict setValue:[attributeDict objectForKey:key]
forKey:key];
}
// If there's already an item for this key, it means we need to create an array
id existingValue = [parentDict objectForKey:elementName];
if (existingValue){
NSMutableArray *array = nil;
if ([existingValue isKindOfClass:[NSMutableArray class]]){
// The array exists, so use it
array = (NSMutableArray *) existingValue;
}
else{
// Create an array if it doesn't exist
array = [NSMutableArray array];
[array addObject:existingValue];
// Replace the child dictionary with an array of children dictionaries
[parentDict setObject:array forKey:elementName];
}
// Add the new child dictionary to the array
[array addObject:childDict];
}
else{
// No existing value, so update the dictionary
[parentDict setObject:childDict forKey:elementName];
}
// Update the stack
[dictionaryStack addObject:childDict];
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
// Update the parent dict with text info
NSMutableDictionary *dictInProgress = [dictionaryStack lastObject];
// Pop the current dict
[dictionaryStack removeLastObject];
// Set the text property
if ([textInProgress length] > 0){
if ([dictInProgress count] > 0){
[dictInProgress setObject:textInProgress forKey:kXMLReaderTextNodeKey];
}
else{
// Given that there will only ever be a single value in this dictionary, let's replace the dictionary with a simple string.
NSMutableDictionary *parentDict = [dictionaryStack lastObject];
id parentObject = [parentDict objectForKey:elementName];
// Parent is an Array
if ([parentObject isKindOfClass:[NSArray class]]){
[parentObject removeLastObject];
[parentObject addObject:textInProgress];
}
// Parent is a Dictionary
else{
[parentDict removeObjectForKey:elementName];
[parentDict setObject:textInProgress forKey:elementName];
}
}
// Reset the text
[textInProgress release];
textInProgress = [[NSMutableString alloc] init];
}
// If there was no value for the tag, and no attribute, then remove it from the dictionary.
else if ([dictInProgress count] == 0){
NSMutableDictionary *parentDict = [dictionaryStack lastObject];
[parentDict removeObjectForKey:elementName];
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
// Build the text value
[textInProgress appendString:[string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]];
}
- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError
{
// Set the error pointer to the parser's error object
if (errorPointer)
errorPointer = parseError;
}
#end
Use it:
NSMutableDictionary *yourDic= (NSMutableDictionary *)[XMLReader dictionaryForXMLData:yourData error:&error];
I am currently doing an application which make use of the RSS Feed from http://www.learnerstogether.net/. However i keep getting the error unable to download the XML data from the website. Can someone tell me what is wrong.
#implementation Parser
#synthesize items, responseData;
#synthesize currentTitle;
#synthesize currentDate;
#synthesize currentSummary;
#synthesize currentLink;
#synthesize currentPodcastLink;
- (void)parseRssFeed:(NSString *)url withDelegate:(id)aDelegate {
[self setDelegate:aDelegate];
responseData = [[NSMutableData data] retain];
NSURL *baseURL = [[NSURL URLWithString:url] retain];
NSURLRequest *request = [NSURLRequest requestWithURL:baseURL];
[[[NSURLConnection alloc] initWithRequest:request delegate:self] autorelease];
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
[responseData setLength:0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[responseData appendData:data];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
NSString * errorString = [NSString stringWithFormat:#"Unable to download xml data (Error code %i )", [error code]];
UIAlertView * errorAlert = [[UIAlertView alloc] initWithTitle:#"Error loading content" message:errorString delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[errorAlert show];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
self.items = [[NSMutableArray alloc] init];
NSXMLParser *rssParser = [[NSXMLParser alloc] initWithData:responseData];
[rssParser setDelegate:self];
[rssParser parse];
}
#pragma mark rssParser methods
- (void)parserDidStartDocument:(NSXMLParser *)parser {
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{
currentElement = [elementName copy];
if ([elementName isEqualToString:#"item"]) {
item = [[NSMutableDictionary alloc] init];
self.currentTitle = [[NSMutableString alloc] init];
self.currentDate = [[NSMutableString alloc] init];
self.currentSummary = [[NSMutableString alloc] init];
self.currentLink = [[NSMutableString alloc] init];
self.currentPodcastLink = [[NSMutableString alloc] init];
}
// podcast url is an attribute of the element enclosure
if ([currentElement isEqualToString:#"enclosure"]) {
[currentPodcastLink appendString:[attributeDict objectForKey:#"url"]];
}
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
if ([elementName isEqualToString:#"item"]) {
[item setObject:self.currentTitle forKey:#"title"];
[item setObject:self.currentLink forKey:#"link"];
[item setObject:self.currentSummary forKey:#"summary"];
[item setObject:self.currentPodcastLink forKey:#"podcastLink"];
// Parse date here
NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
[dateFormatter setDateFormat:#"E, d LLL yyyy HH:mm:ss Z"]; // Thu, 18 Jun 2010 04:48:09 -0700
NSDate *date = [dateFormatter dateFromString:self.currentDate];
[item setObject:date forKey:#"date"];
[items addObject:[item copy]];
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
if ([currentElement isEqualToString:#"title"]) {
[self.currentTitle appendString:string];
} else if ([currentElement isEqualToString:#"link"]) {
[self.currentLink appendString:string];
} else if ([currentElement isEqualToString:#"description"]) {
[self.currentSummary appendString:string];
} else if ([currentElement isEqualToString:#"pubDate"]) {
[self.currentDate appendString:string];
NSCharacterSet* charsToTrim = [NSCharacterSet characterSetWithCharactersInString:#" \n"];
[self.currentDate setString: [self.currentDate stringByTrimmingCharactersInSet: charsToTrim]];
}
}
- (void)parserDidEndDocument:(NSXMLParser *)parser {
if ([_delegate respondsToSelector:#selector(receivedItems:)])
[_delegate receivedItems:items];
else
{
[NSException raise:NSInternalInconsistencyException
format:#"Delegate doesn't respond to receivedItems:"];
}
}
#pragma mark Delegate methods
- (id)delegate {
return _delegate;
}
- (void)setDelegate:(id)new_delegate {
_delegate = new_delegate;
}
- (void)dealloc {
[items release];
[responseData release];
[super dealloc];
}
#end
Your error has absolutely nothing to do with the RSS parsing aspect of this. What's more, you haven't even pasted in the full error. You should log the error object itself in your implementation of -connection:didFailWithError:. That should give you a human-readable description of what went wrong.
i try to parse within my iPhone SDK 4
http://de.news.search.yahoo.com/news/rss?p=iphone&ei=UTF-8&fl=0&x=wrt
there are some german umlaute
<description><![CDATA[Mehr als die Hälfte der Belegschaft des weltweit größten]]></description>
As I read in another forum as long they are wrapped in CDATA it should be fine.
But in the moment the parser found the element "description"
he breaks with:
error parsing XML: Unable to download story feed from web site (Error code 9 ) http://de.news.search.yahoo.com/news/rss?p=iphone&ei=UTF-8&fl=0&x=wrt
The english feeds works fine !? So its something with this umlaute, but what can i do?
greets
chris
JUST FOR UNDERSTANDING .. HERE MY WHOLE PARSER
- (void)parseXMLFileAtURL:(NSString *)URL {
aktuelleUrl = URL;
stories = [[NSMutableArray alloc] init];
NSURL *xmlURL = [NSURL URLWithString:aktuelleUrl];
// here, for some reason you have to use NSClassFromString when trying to alloc NSXMLParser, otherwise you will get an object not found error
// this may be necessary only for the toolchain
rssParser = [[NSXMLParser alloc] initWithContentsOfURL:xmlURL];
// Set self as the delegate of the parser so that it will receive the parser delegate methods callbacks.
[rssParser setDelegate:self];
// Depending on the XML document you're parsing, you may want to enable these features of NSXMLParser.
[rssParser setShouldProcessNamespaces:NO];
[rssParser setShouldReportNamespacePrefixes:NO];
[rssParser setShouldResolveExternalEntities:NO];
[rssParser parse];
}
- (void)parserDidStartDocument:(NSXMLParser *)parser{
//NSLog(#"found file and started parsing");
}
- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError {
NSString * errorString = [NSString stringWithFormat:#"Unable to download story feed from web site (Error code %i ) %#", [parseError code], aktuelleUrl];
NSLog(#"error parsing XML: %#", errorString);
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{
NSLog(#"found this element: %#", elementName);
currentElement = [elementName copy];
if ([elementName isEqualToString:#"channel"]) {
channel1item2 = 1;
// clear out our story item caches...
// item = [[NSMutableDictionary alloc] init];
currentTitle = [[NSMutableString alloc] init];
// currentDate = [[NSMutableString alloc] init];
currentSummary = [[NSMutableString alloc] init];
currentLink = [[NSMutableString alloc] init];
}
if ([elementName isEqualToString:#"item"]) {
channel1item2 = 2;
// clear out our story item caches...
item = [[NSMutableDictionary alloc] init];
currentTitle = [[NSMutableString alloc] init];
currentDate = [[NSMutableString alloc] init];
currentSummary = [[NSMutableString alloc] init];
currentLink = [[NSMutableString alloc] init];
currentEncoded = [[NSMutableString alloc] init];
}
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
//NSLog(#"ended element: %# c1i2: %i", elementName, channel1item2);
if (channel1item2 == 1) {
if (![currentTitle isEqualToString:#""]) { aCurrentTitle = currentTitle; }
if (![currentLink isEqualToString:#""]) { aCurrentLink = currentLink; }
if (![currentSummary isEqualToString:#""]) {aCurrentSummary = currentSummary; }
}
else if ([elementName isEqualToString:#"item"]) {
[item setObject:currentTitle forKey:#"title"];
[item setObject:currentLink forKey:#"link"];
[item setObject:currentSummary forKey:#"summary"];
[item setObject:currentDate forKey:#"date"];
[item setObject:currentEncoded forKey:#"content:encoded"];
[stories addObject:[item copy]];
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
//NSLog(#"found characters: %#", string);
// save the characters for the current item...
if ([currentElement isEqualToString:#"title"]) {
[currentTitle appendString:string];
} else if ([currentElement isEqualToString:#"link"]) {
[currentLink appendString:string];
//NSLog(#"parselink '%#'",string);
} else if ([currentElement isEqualToString:#"description"]) {
[currentSummary appendString:string];
} else if ([currentElement isEqualToString:#"pubDate"]) {
[currentDate appendString:string];
} else if ([currentElement isEqualToString:#"content:encoded"]) {
[currentEncoded appendString:string];
}
else if ([currentElement isEqualToString:#"media:content"]) {
//NSLog(#"mediacontent %#",string);
}
}
- (void)parserDidEndDocument:(NSXMLParser *)parser {
// NSLog(#"all done!");
//NSLog(#"stories array has %d items", [stories count]);
}
Perhaps look into -stringWithContentsOfURL:usedEncoding:error: to download the XML:
NSError *error = nil;
NSStringEncoding encoding;
NSString *xmlFeedStr = [NSString stringWithContentsOfURL:[NSURL URLWithString:#"http://de.news.search.yahoo.com/news/rss?p=iphone&ei=UTF-8&fl=0&x=wrt"] usedEncoding:&encoding error:&error];
NSXMLParser *rssParser = [[NSXMLParser alloc] initWithData:[xmlFeedStr dataUsingEncoding:encoding allowLossyConversion:YES]];
...
[rssParser release];
From the documentation:
NSXMLParserInvalidCharacterError = 9
Perhaps the document is not really encoded in UTF-8?
Now I solved it different. Wrote my own XML parser just simple for my needs and with the following routine, i found in some forum, i encode the xml string. Also I marked the answer above as 'accepted' as it lead me into the right direction.
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)s {
[resultString appendString:s];
}
- (NSString*)convertEntiesInString:(NSString*)s {
resultString = [[NSMutableString alloc] init];
if(s == nil) {
//NSLog(#"ERROR : Parameter string is nil");
}
NSString* xmlStr = [NSString stringWithFormat:#"<d>%#</d>", s];
NSData *data = [xmlStr dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES];
NSXMLParser* xmlParse = [[NSXMLParser alloc] initWithData:data];
[xmlParse setDelegate:self];
[xmlParse parse];
NSString* returnStr = [[NSString alloc] initWithFormat:#"%#",resultString];
return returnStr;
}
objectsResultStr = [self convertEntiesInString:orgString]];
I finally get no leaks in my app but I still manage to get my app to crash from time to time ... it is really rare but it pisses me off ;)
Here is what I get :
2010-05-11 19:36:29.487 Infonul[2457:20b] *** -[NSCFString _setParserError:]: unrecognized selector sent to instance 0x3cddb80
[Session started at 2010-05-11 19:36:29 +0200.]
2010-05-11 19:36:29.487 Infonul[2457:20b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSCFString _setParserError:]: unrecognized selector sent to instance 0x3cddb80'
2010-05-11 19:36:29.488 Infonul[2457:20b] Stack: (
9479259,
2423766587,
9861179,
9430646,
9283266,
4372334,
56536,
4191652,
4191507,
12699064,
12697112,
12697826,
12697826,
12700310,
12359637,
9263329,
9260104,
825261,
825458,
23633923
)
Here is where it seems to fail :
// after having downloaded the file to parse
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
CommentsParserDelegate *commentsParserDelegate = [[CommentsParserDelegate alloc] initWithController:self];
//commentsParserDelegate.commentController = self;
commentsParser = [[NSXMLParser alloc] initWithData:self.activeDownload];
[commentsParser setDelegate:commentsParserDelegate];
[commentsParser parse]; //last function called before crash
}
No idea why app crashes and I don't understand what the debugger is trying to tell me :D
Hopefully, someone gets some idea ;)
Thank you.
Gotye.
The debugger is trying to tell you that you (or, more likely, the framework) are trying to invoke a method called _setParserError on an object of class NSString. There's no such method in NSString.
Here is the code of "CommentsParserDelegate.m"
//
// CommentsParserDelegate.m
// Infonul
//
// Created by eef16514f684e5d on 26/03/10.
// Copyright 2010 __MyCompanyName__. All rights reserved.
//
#import "CommentsParserDelegate.h"
#implementation CommentsParserDelegate
#synthesize currentElement;
//#synthesize commentController;
- (id)initWithController:(CommentsViewController *)comment {
if (self = [super init]) {
commentController = comment;
months = [[NSArray alloc] initWithObjects:#"Jan.",#"Fév.",#"Mars",#"Avril",#"Mai",#"Juin",#"Juil.",#"Août",#"Sept.",#"Oct.",#"Nov.",#"Déc.",nil];
}
return self;
}
- (void)parserDidStartDocument:(NSXMLParser *)parser {
comments = [[NSMutableArray alloc] init];
//currentElement = [[NSString alloc] init];
currentContent = [[NSMutableString alloc] init];
currentAuthor = [[NSMutableString alloc] init];
currentDate = [[NSMutableString alloc] init];
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{
self.currentElement = elementName;
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
if ([elementName isEqualToString:#"item"]) {
// save values to an item, then store that item into the array...
CommentRecord *comment = [[CommentRecord alloc] init];
[comment setAuthor:[[[NSString alloc] initWithString:[currentAuthor stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]] autorelease]];
[currentAuthor setString:#""];
[comment setContent:[[[NSString alloc] initWithString:[currentContent stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]] autorelease]];
[currentContent setString:#""];
NSString *tempDate = [[[NSString alloc] initWithString:[currentDate stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]] autorelease];
NSMutableString *tempString = [[NSMutableString alloc] initWithString:[tempDate substringToIndex:2]];
NSString *month = [[tempDate substringFromIndex:3] substringToIndex:2];
[tempString appendString:#" "];
[tempString appendString:[months objectAtIndex:[month intValue]-1]];
[tempString appendString:#" "];
[tempString appendString:[[tempDate substringFromIndex:6] substringToIndex:4]];
[tempString appendString:#" à "];
[tempString appendString:[[tempDate substringFromIndex:11] substringToIndex:8]];
[comment setDate:[[[NSString alloc] initWithString:tempString] autorelease]];
[tempString release];
[currentDate setString:#""];
[comments addObject:comment];
[comment release];
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
if (([currentElement isEqualToString:#"author"])) {
[currentAuthor appendString:[self flattenTEXT:string]];
}
else if (([currentElement isEqualToString:#"content"])) {
[currentContent appendString:string];
}
else if (([currentElement isEqualToString:#"date"])) {
[currentDate appendString:string];
}
}
- (NSString *)flattenTEXT:(NSString *)link
{
//link = [link stringByReplacingOccurrencesOfString:#" " withString:#""];
link = [link stringByReplacingOccurrencesOfString:#"\n" withString:#""];
link = [link stringByReplacingOccurrencesOfString:#"\t" withString:#""];
link = [link stringByReplacingOccurrencesOfString:#"\r" withString:#""];
return link;
}
- (void)parserDidEndDocument:(NSXMLParser *)parser {
[currentDate release];
[currentContent release];
[currentAuthor release];
[self.currentElement release];
[commentController displayData:comments];
}
- (void)dealloc {
[comments release];
[months release];
[super dealloc];
}
/*
- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError
{
NSLog(parseError.description);
}
*/
#end
Would that help ?
Is the log always saying that the selector is being sent to an NSString object, or does the object type vary? If it varies, it's usually a sign of a memory management problem.
How could I display arrayData in table view cell?
I want to set the table view cell's label text to the 'ename' from the data parsed.
Please help me out.
Thanks in Advance.
- (void)viewDidLoad {
NSString *url = [NSString stringWithFormat:#"http://mmabigshow.com/app/get_result_from_query.php?q=select * from event"];
NSString *escapedUrl = [url stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
[self performSelector:#selector(startParsing:) withObject:escapedUrl afterDelay:1.0];
NSLog(#"View Did Load End");*/
[super viewDidLoad];
}
- (void) startParsing: (NSString *) query{
NSLog(#"Start Of Parsing");
NSURL *xmlURL = [[NSURL alloc] initWithString:query];
NSData *myData = [NSData dataWithContentsOfURL:xmlURL];
NSString *myStr = [[NSString alloc] initWithData:myData encoding:NSWindowsCP1252StringEncoding];
myStr = [myStr stringByReplacingOccurrencesOfString:#"encoding=\"windows-1252\"" withString:#""];
NSData* aData = [myStr dataUsingEncoding:NSUTF8StringEncoding];
rssParser = [[NSXMLParser alloc] initWithData:aData];
[rssParser setDelegate:self];
[rssParser setShouldProcessNamespaces:NO];
[rssParser setShouldReportNamespacePrefixes:NO];
[rssParser setShouldResolveExternalEntities:NO];
[rssParser parse];
NSLog(#"End of Parsing");
}
#pragma mark xml parser
#pragma mark -
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{
currentElement = [elementName copy];
if ([elementName isEqualToString:#"table"]){
item = [[NSMutableDictionary alloc] init];
currentEid = [[NSMutableString alloc] init];
currentEname = [[NSMutableString alloc] init];
currentEurl = [[NSMutableString alloc] init];
dataArray = [[NSMutableArray alloc] init];
}
//NSLog(#"didStartElement");
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
if ([elementName isEqualToString:#"table"]) {
// save values to an item, then store that item into the array...
[item setObject:currentEname forKey:#"ename"];
//NSLog(#"%#",item);
[dataArray addObject:[[item copy] autorelease]];
//NSLog(#"%#",dataArray);
}
[currentEid release];
[currentEname release];
[currentEurl release];
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
if ([currentElement isEqualToString:#"eid"]) {
[currentEid appendString:string];
} else if ([currentElement isEqualToString:#"ename"]) {
[currentEname appendString:string];
//NSLog(#"%#",currentEname);
} else if ([currentElement isEqualToString:#"eurl"]) {
[currentEurl appendString:string];
}
// NSLog(#"foundCharacters");
}
#pragma mark -
#pragma mark Table Data Source Methods
- (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section {
NSLog(#"numberOfRowsInSection");
return [self.dataArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"cellForRowAtIndexPath");
static NSString *CustomCellIdentifier = #"CustomCellIdentifier ";
TableDetailsCell *cell = (TableDetailsCell *)[tableView dequeueReusableCellWithIdentifier: CustomCellIdentifier];
if (cell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"TableDetailsCell" owner:self options:nil];
for (id oneObject in nib)
if ([oneObject isKindOfClass:[TableDetailsCell class]])
cell = (TableDetailsCell *)oneObject;
}
NSUInteger row = [indexPath row];
NSDictionary *rowData = [self.dataArray objectAtIndex:row];
//NSLog(#"%#",rowData);
cell.text = [rowData objectForKey:#"ename"];
cell.labelName.text= [rowData objectForKey:#"ename"];
return cell;
}
I believe your problem is that you are not referring to dataArray as self.dataArray all the time which may cause your program not to work properly.
Then assign via
cell.textLabel.text = [self.dataArray objectAtIndex:indexRow.row];
Hope this helped
Seb Kade
"I'm here to help"
Apple's SeismicXML app does exactly this. Look at the rootViewController's cellForRowAtIndexPath.
Also, make sure your tableview has it's delegate and datasource set correctly in Interface Builder (if you chose to use it).