Im trying to parse a xml feed in my app... The xml file is in this url
feeds.feedburner.com/blogspot/TUvAW?format=xml
The problem is that when I access the description segment it diplays different special symbols such as quotation marks. This is one of the descripton segments im trying to parse from my xml:
<description>Este es mi blog 3<img src="http://feeds.feedburner.com/~r/blogspot/TUvAW/~4/URCV9ModTR0" height="1" width="1"/></description>
Im parsing it with the NSXMLParser, these are the method I'm using in my:
XMLParser.m
- (void) parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
currentNodeContent = (NSMutableString *) [string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
}
- (void) parser:(NSXMLParser *)parser didStartElement:(NSString *)elementname namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
if ([elementname isEqualToString:#"item"])
{
currentFeed = [Feed alloc];
isStatus = YES;
}
if ([elementname isEqualToString:#"author"])
{
isStatus = NO;
}
}
- (void) parser:(NSXMLParser *)parser didEndElement:(NSString *)elementname namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if (isStatus)
{
if ([elementname isEqualToString:#"description"])
{
currentFeed.description = currentNodeContent;
NSLog(#"%#",currentNodeContent);
}
if ([elementname isEqualToString:#"title"])
{
currentFeed.content = currentNodeContent;
NSLog(#"%#",currentNodeContent);
}
if ([elementname isEqualToString:#"link"])
{
currentFeed.WVUrl = currentNodeContent;
NSLog(#"%#",currentNodeContent);
}
}
if ([elementname isEqualToString:#"item"])
{
[self.feeds addObject:currentFeed];
currentFeed = nil;
currentNodeContent = nil;
}
}
Im using those NSLogs to track the strings that Im getting from the parse but my description node content is always showing just this : >
The title and link nodes are displaying perfectly.
I want to get all that string from the description node to use it later but simply I can't, I dont know whats going wrong with this.
The problems have been outlined by Abhishek, Rob and me. But I think it's worth to summarize it and show the correct solution.
The main problem is that parser:foundCharacters: is called several times for the <description> tag, each call providing a piece of the description.
The solution is to concatenate the pieces:
XMLParser.h:
NSMutableString* currentNodeContent;
XMLParser.m:
- (void) parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
if (currentNodeContent == nil)
currentNodeContent = [[NSMutableString alloc] initWithCapacity: 20];
[currentNodeContent appendString: [string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]];
}
- (void) parser:(NSXMLParser *)parser didStartElement:(NSString *)elementname namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
if ([elementname isEqualToString:#"item"])
{
currentFeed = [Feed alloc];
isStatus = YES;
}
if ([elementname isEqualToString:#"author"])
{
isStatus = NO;
}
}
- (void) parser:(NSXMLParser *)parser didEndElement:(NSString *)elementname namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if (isStatus)
{
if ([elementname isEqualToString:#"description"])
{
currentTweet.description = currentNodeContent;
NSLog(#"%#",currentNodeContent);
}
if ([elementname isEqualToString:#"title"])
{
currentTweet.content = currentNodeContent;
NSLog(#"%#",currentNodeContent);
}
if ([elementname isEqualToString:#"link"])
{
currentFeed.WVUrl = currentNodeContent;
NSLog(#"%#",currentNodeContent);
}
}
if ([elementname isEqualToString:#"item"])
{
[self.feeds addObject:currentFeed];
currentFeed = nil;
[currentNodeContent release];
currentNodeContent = nil;
}
}
The problem in the Xml file is use of "&" Character.
Do one this just get the xml data in one string and then replace "&" with any unique string and then parse your xml.
While showing or use of xml data just check if the string you are getting contains the same unique string in it then replace that string with the "&".
Related
I am new in iphone Development, I don't know much about parsing. But I tried following code to get the distance element text. I am doing XMl parsing Of following link:
http://maps.googleapis.com/maps/api/directions/xml?origin=30.9165904,75.8634752&destination=30.89314000,75.86938000&sensor=true
Please check my code which i have tried:
-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:
(NSDictionary *)attributeDict
{
currentElement = [elementName copy];
if([currentElement isEqualToString:#"distance"])
{
NSLog(#"ENTER IN distance");
text = [[NSMutableString alloc]init];
{
dictionary = [NSMutableDictionary dictionaryWithObjectsAndKeys:text,#"text",nil];
}
}
}
-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
if ([currentElement isEqualToString:#"text"])
{
[dictionary setObject:text forKey:currentElement];
[text appendString:string];
NSLog(#"text....%#",text);
}
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:
(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if ([elementName isEqualToString:#"distance"])
{
[distanparsingarray addObject:dictionary];
}
}
By using above method I am getting the text both of distance and duration. But I want only distance text. Please tell me what I am doing wrong in above code.
thanks in advance.
You have to manage it by below way.
Add on BOOL variable at class level. Set it when you identify currentElement as distance.
Inside found characters append string to text only when above BOOL is true.
Make this BOOL as false in didEndElement when currentElement is not equal to distance.
-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:
(NSDictionary *)attributeDict
{
currentElement = [elementName copy];
if([currentElement isEqualToString:#"distance"])
{
flag = TRUE; //created at class level.
NSLog(#"ENTER IN distance");
text = [[NSMutableString alloc]init];
{
dictionary = [NSMutableDictionary dictionaryWithObjectsAndKeys:text,#"text",nil];
}
}
}
-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
if ([currentElement isEqualToString:#"text"] && flag == TRUE)
{
[dictionary setObject:text forKey:currentElement];
[text appendString:string];
NSLog(#"text....%#",text);
}
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:
(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if ([elementName isEqualToString:#"distance"])
{
[distanparsingarray addObject:dictionary];
flag = FALSE;
}
}
I am parsing data using NSXMLParser.
I am able to get the parsed data. But when I add it to the NSMutableArray using addObject, the array is empty.
I am using the latest Xcode version.
Can someone please help me out.
The array I am working on is identificationTypes1
-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{
if ([elementName isEqualToString:#"Books"]) {
}
if ([elementName isEqualToString:#"Book"]) {
if ([elementName isEqualToString:#"title"]) {
self.identificationTypes1 =[[NSMutableArray alloc]init];
}
}
}
-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
if (!currentElementValue) {
currentElementValue =[[NSMutableString alloc]initWithString:string];
}
else {
[currentElementValue appendString:string];
}
}
-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
if ([elementName isEqualToString:#"Books"]) {
NSLog(#"Count is %#",[identificationTypes1 count]);
return;
}
if ([elementName isEqualToString:#"Book"]) {
}
if ([elementName isEqualToString:#"title"]) {
NSLog(#"Curre value is %#",currentElementValue);
[self.identificationTypes1 addObject:currentElementValue];
}
currentElementValue = nil;
}
NSMutabeArray *myArray = [[NSMUtableArray alloc]init];
[myArray addObject:<XML Data>];
You cannot nest elements as you have in didStartElement. Parsers do not allow that.
Take out the title out on its own and retest. You need to make new variables that are accessed conditionally.
I am Parsing Web urls from server and storing them in Strings and then displaying it on Webview. But now when i am parsing Spanish words like
http://litofinter.es.milfoil.arvixe.com/litofinter/PDF/Presentación_LITOFINTER_(ES).pdf
it is accepting it
PDF File Name ++++++ http://litofinter.es.milfoil.arvixe.com/litofinter/PDF/Presentaci
PDF File Name ++++++ ón_LITOFINTER_(ES).pdf
i.e two different strings... i know i have to make small change that is append the string but i am not able to do it now, can anyone help me out. Here is my code :-
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
currentElement = elementName;
if([currentElement isEqualToString:#"category"]) {
NSLog(#"Current element in Category:- %#",currentElement);
obj = [[Litofinter alloc]init];
obj.productsArray = [[NSMutableArray alloc]init];
}
if([currentElement isEqualToString:#"Product"]) {
obj.oneObj = [[Products alloc]init];
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
if([currentElement isEqualToString:#"Logo"]) {
obj.cLogo=[NSString stringWithFormat:#"%#",string];
NSLog(#"Logo to be saved in Array :- %#",obj.cLogo);
}
if([currentElement isEqualToString:#"Name"]) {
obj.cName=[NSString stringWithFormat:#"%#",string];
NSLog(#"Name to be saved in Array :- %#",string);
}
if([currentElement isEqualToString:#"cid"]) {
obj.cId=(int)[NSString stringWithFormat:#"%#",string];
NSLog(#"CID to be saved in Array :- %#",string);
}
if([currentElement isEqualToString:#"pid"]) {
//obj.oneObj.id = (int)[NSString stringWithFormat:#"%#",oneBook.id];
obj.oneObj.id = (int)[oneBook.id intValue];
}
if([currentElement isEqualToString:#"Title"]) {
obj.oneObj.title = [NSString stringWithFormat:#"%#",string];
}
if([currentElement isEqualToString:#"Thumbnail"]) {
obj.oneObj.thumbnail= [NSString stringWithFormat:#"%#",string];
}
// problem occuriing while parsing Spanish characters...
if([currentElement isEqualToString:#"pdf"]) {
obj.oneObj.pdf = [NSString stringWithFormat:#"%#",string];
NSLog(#"PDF File Name ++++++ %#",string);
}
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if([elementName isEqualToString:#"category"]) {
NSLog(#"Current element in End Element Category:- %#",currentElement);
[TableMutableArray addObject:obj];
}
if([elementName isEqualToString:#"Product"]) {
[obj.productsArray addObject:obj.oneObj];
}
currentElement = #"";
}
I will be thankful to you.
I found the answer :
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
currentElement = elementName;
// MOdified
else if([currentElement isEqualToString:#"pdf"]) {
// obj.oneObj.pdf = [NSString stringWithFormat:#"%#",string];
// NSLog(#"PDF File Name ++++++ %#",string);
NSMutableString *outputBuilder = [[NSMutableString alloc]init] ;
[outputBuilder appendString:[NSString stringWithFormat:#"%#", self.pdfString]];
[outputBuilder appendString:[NSString stringWithFormat:#"%#", string]];
self.pdfString = outputBuilder;
[outputBuilder release];
}
else
{
self.pdfString = string;
}
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if([currentElement isEqualToString:#"pdf"])
{
obj.oneObj.pdf = self.pdfString;
NSLog(#"PDF File Name ++++++ %#",obj.oneObj.pdf);
}
currentElement = #"";
}
and a small change also that is where i am passing this use this:-
NSString *urlString = [appDelegate.currentBookPressed stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
declare NSString in .h file;
in Did Start parse
str=#"";
if([currentElement isEqualToString:#"pdf"]) {
str=[str stringByAppendingString:string];
obj.oneObj.pdf = [NSString stringWithFormat:#"%#",str];
NSLog(#"PDF File Name ++++++ %#",str);
}
i m not able to get processing values beyond "iid". giving exception:
[ setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key iid.'
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName
attributes:(NSDictionary *)attributeDict {
if([elementName isEqualToString:#"NewDataSet"])
{
appDelegate.books = [[NSMutableArray alloc] init];
}
else if([elementName isEqualToString:#"Table"])
{
if([elementName isEqualToString:#"id"])
{
{
aBook = [[Book alloc] init];
}
}
NSLog(#"Processing Element: %#", elementName);
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
if(!currentElementValue)
currentElementValue = [[NSMutableString alloc] initWithString:string];
else
{
[currentElementValue appendString:string];
NSLog(#"Processing Value: %#", currentElementValue);
}
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
//if([elementName isEqualToString:#"Tablesreturn"])
//return;
if([elementName isEqualToString:#"Table"])
{
[appDelegate.books addObject:aBook];
[aBook release];
aBook = nil;
}
else
[aBook setValue:currentElementValue forKey:elementName];
[currentElementValue release];
currentElementValue = nil;
}
It's not finding the iid value. It's case sensitive, so check if you're using the wrong case in your label name.
If you're not looking for too many values maybe you can just do a manual if then else for all the xml nodes you're interested in.
something like -
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
if([elementName isEqualToString:#"Table"])
{
[appDelegate.books addObject:aBook];
[aBook release];
aBook = nil;
}
else if([elementName isEqualToString:#"xyz"])
{
[aBook setValue:currentElementValue forKey:#"xyz"];
}
// and so on, for the rest of the nodes.
[currentElementValue release];
currentElementValue = nil;
}
in ur Book class verify all tags or fields specified in .h file.......reply me
like Table, Tablesreturn.......all of them.
and synthesize all of them
I've been trying for some time now to get xml parser working leak free and efficient but so far unsuccessful. I've removed additional fields as they are all the same.
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{
currentElement = [[elementName copy] autorelease];
if ([elementName isEqualToString:#"source"]) {
if (!currentID) {
overlays = [[NSMutableArray alloc] init];
currentID = [[NSMutableString alloc] init];
} else {
[currentID release];
currentID = nil;
currentID = [[NSMutableString alloc] init];
}
}
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
if ([elementName isEqualToString:#"source"]) {
overlay = [[NSMutableDictionary alloc] init];
[overlay setObject:currentID forKey:#"id"];
[overlays insertObject:overlay atIndex:[overlays count]];
[overlay release];
overlay = nil;
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
string = [string stringByReplacingOccurrencesOfString:#"\n" withString:#""];
string = [string stringByReplacingOccurrencesOfString:#"\t" withString:#""];
if ([currentElement isEqualToString:#"id"]) {
[self.currentID appendString:string];
}
}
- (void)parserDidEndDocument:(NSXMLParser *)parser {
[currentID release];
currentID = nil;
//[self addResources];
}
Any help would be appreciated.
If you have declared properties for your ivars I would recommend to use them. This makes memory management easier. This is how I would write your code:
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{
self.currentElement = elementName;
if ([elementName isEqualToString:#"source"]) {
if (!self.currentID) {
self.overlays = [NSMutableArray array];
self.currentID = [NSMutableString string];
} else {
self.currentID = [NSMutableString string];
}
}
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
if ([elementName isEqualToString:#"source"]) {
[self.overlays addObject:
[NSDictionary dictionaryWithObjectsAndKeys:self.currentID,#"id",nil]];
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
string = [string stringByReplacingOccurrencesOfString:#"\n" withString:#""];
string = [string stringByReplacingOccurrencesOfString:#"\t" withString:#""];
if ([self.currentElement isEqualToString:#"id"]) {
[self.currentID appendString:string];
}
}
- (void)parserDidEndDocument:(NSXMLParser *)parser {
self.currentID = nil;
}
You might also want to try Build&Analyse for your code. this may point out where you are leaking.