NSXMLParser works not correct with symbols like “ - iphone

I have some problems with parsing of xml in my iPhone Application. Here is some part of xml code that I want to parse with standard NSXMLParser parser.
<item>
<title>AMNews: Facebook & Twitter Updates Might Lead To Burglary, Oldham School Violates DPA, Amazon Cloud “Burstsâ€</title>
<link>http://www.itproportal.com/2011/04/22/amnews-facebook-twitter-updates-might-lead-to-burglary-oldham-school-violates-dpa-amazon-cloud-bursts/</link>
<description>People announcing their holiday plans on social networking platforms like Facebook and Twitter are putting themselves at risks from thieves and burglars. A new study ha</description>
<author>ravimandalia#itproportal.com (Ravi Mandalia)</author>
<pubDate>Fri, 22 Apr 2011 08:19:36 +0100</pubDate>
<guid>http://cdn.itproportal.com/photos/facebook-logo-4_thumb80x80.png</guid>
</item>
How you can see in
<title>AMNews: Facebook & Twitter Updates Might Lead To Burglary, Oldham School Violates DPA, Amazon Cloud “Burstsâ€</title>
title tag some strange symbols appear "“" "â". In function
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string;
I am trying to get title and save it, but my parser works wrong. Parser take only text after "“" symbol !!!
What can I do and can anybody tell me what happens with parse ? Thanks a lot !!!

Can you show us your implementation of -parser:foundCharacters:? How do you store string?
I have also once used an NSXMLParser with special characters in the XML file, and it worked without problems.

Here is implementation of -parser:foundCharacters:
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
//in case of unusable tags
if (currentArticle == nil) {
return;
}
// Get Title.
if ([currentElement isEqualToString:#"title"]) {
[self.currentArticle setTheTitle:string];
// Get Description.
} else if ([currentElement isEqualToString:#"description"]) {
string = [string stringByReplacingOccurrencesOfString: #"\n" withString: #"" ];
[self.currentArticle setTheSummary:string];
} else if ([currentElement isEqualToString:#"link"]) {
[self.currentArticle setTheMainLink:string];
} else if([currentElement isEqualToString:#"guid"]){
[self.currentArticle setTheImageLink:string];
} else if ([currentElement isEqualToString:#"pubDate"]) {
[self.currentArticle setThePubDate:string];
} else if([currentElement isEqualToString:#"author"]){
[self.currentArticle setTheAuthor:string];
}
}
I have notice that parser get title two times at first time from the begin to the “ and second time from “ to end. Like in my feed there are two title tags.

Related

How can I parse XML of having multiple Nodes with same name and show in different controller?

See the XML below
http://sosmoths.com/.xml/moths.xml
This XML having multiple images name, I have to show the different title(There are four title) in their respective Controller.
I have 4 controller, and have to show each moth value in different Controller, along with their multiple images values, how can I do it?
I can make single object of should I make four objects?
I am a bit confused in it, please help me.
This XML having multiple images name, I have to show the different
title(There are four title) in their respective Controller. I have 4
controller, and have to show each moth value in different Controller,
along with their multiple images values, how can I do it?
This sounds less like an XML parsing problem and more like an app architecture problem.
That XML basically describes some data and said data would typically be represented by objects in your application. You could go with a CoreData based solution whereby you parse the XML into a local CoreData store (in memory or on disk, matters not) and then display the managed objects as per usual.
Or, assuming that is representative of a typical set of data, you could parse it into your own hand rolled objects (or, even, dictionaries and arrays), then display from there.
There are dozens of questions about parsing XML on SO (and via Google).
The second part of your question hasn't been addressed. Basically, you need to properly layer your app into the model-view-controller pattern. Your model layer would parse the XML and create an object graph that represents the data. Each controller would have a reference to that single model.
This will work fine as long as your app is read only. If the various controllers are expected to also edit the object graph, then it'll need to be a bit more complex in that you'll have to deal with change propagation (this is where CoreData shines; it makes change management, propagation, validation, and undo relatively straightforward).
With TBXML you can easily parse the xml and it will convert it into objects to use:
http://www.tbxml.co.uk/TBXML/TBXML_Free.html
and libxml2 is also that you can use easily to parse.
try this it worked properly
-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict{
NSLog(#"%#",elementName);
if([elementName isEqualToString:#"moths"]){
mytblarray=[[NSMutableArray alloc] init];
} else if([elementName isEqualToString:#"moth"]){
tmpdic=[[NSMutableDictionary alloc] init];
}
else if([elementName isEqualToString:#"images"]){
imgArray=[[NSMutableArray alloc] init];
}
}
-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
if(tmpstr!=nil && [tmpstr retainCount]>0){ [tmpstr release]; tmpstr=nil; }
tmpstr=[[NSString alloc] initWithString:string];
}
-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
if([elementName isEqualToString:#"moth"]){
[mytblarray addObject:tmpdic];
[tmpdic release];
}if([elementName isEqualToString:#"images"]){
[tmpdic setValue:imgArray forKey:elementName];
}
else if([elementName isEqualToString:#"image"]){
[imgArray addObject:tmpstr];
}
else if([elementName isEqualToString:#"id"] || [elementName isEqualToString:#"title"]||[elementName isEqualToString:#"description"]){
[tmpdic setValue:tmpstr forKey:elementName];
}
}
-(void)parserDidEndDocument:(NSXMLParser *)parser{
NSLog(#"%#",[imgArray description]);
NSLog(#"%#",[mytblarray description]);
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
//get value like it
NSString *cellValue = [[mytblarray objectAtIndex:indexPath.row] valueForKey:#"id"];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
//get value like it
NSMutableDictionary *dict=[[NSMutableDictionary alloc]initWithDictionary:
[mytblarray objectAtIndex:indexPath.row]];
}

Parse Nested XML Objective C - NSXMLParser

All,
I have XML in the following format:
<linked-list>
<Description>
<desc></desc>
<IP></IP>
</Description>
</linked-list>
This XML statement could have an infinite number of <Description></Description> inside of the <linked-list></linked-list>.
How should I parse this using NSXMLParser? My current code is as follows, but it parses incorrectly.
#implementation XMLParser
#synthesize response;
- (XMLParser *) initXMLParser
{
self = [super init];
// init dictionary of response data
response = [[NSMutableDictionary alloc] init];
return self;
}
//Gets Start Element of SessionData
- (void)parser:(NSXMLParser *)parser
didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qualifiedName
attributes:(NSDictionary *)attributeDict
{
if ([elementName isEqualToString:#"linked-list"])
{
NSLog(#"Found linked-list in the return XML! Continuing...");
//response is a NSMutableArray instance variable
//THIS SHOULD NEVER NEED TO BE USED
if (!response)//if array is empty, it makes it!
{
NSLog(#"Dictionary is empty for some reason, creating...");
response = [[NSMutableDictionary alloc] init];
}
//END: THIS SHOULD NEVER BE USED
return;
}
else
{
currentElementName = elementName;
NSLog(#"Current Element Name = %#", currentElementName);
return;
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
if (!currentElementValue) {
// init the ad hoc string with the value
currentElementValue = [[NSMutableString alloc] initWithString:string];
} else {
[currentElementValue setString:string];
NSLog(#"Processing value for : %#", string);
}
}
//Gets End Element of linked-list
- (void)parser:(NSXMLParser *)parser
didEndElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName {
if ([elementName isEqualToString:#"linked-list"])
{
// We reached the end of the XML document
// dumps dictionary into log
NSLog(#"Dump:%#", [response description]);
return;
}
else
{
//Adds key and object to dictionary
[response setObject:currentElementValue forKey:currentElementName];
NSLog(#"Set values, going around again... brb.");
}
currentElementValue = nil;
currentElementName = nil;
}
#end
Some observations:
An infinite number of WHAT inside of the WHAT?
Assuming there can be more than one Description element, the outer data structure in which you store the contents must be a NSMutableArray, not a dictionary. You then use one mutable dictionary per Description element.
Consequently, in didStartElement:, check if the element name is #"Description" and if so, create a new NSMutableDictionary instance that you store in an ivar.
In foundCharacters:, you always have to append the new characters to the existing currentElementValue because the method can be called multiple times for each element's contents. I see many people do this wrong despite the fact that Apple's sample code clearly demonstrates the correct way.
In didEndElement:, do this:
If the element name is #"desc" or #"IP", assign currentElementValue to the corresponding key in your current mutable dictionary. Don't forget to release currentElementValue before you set it to nil. You currently have a memory leak in your code because you're not doing that.
If the element name is #"Description", add the current mutable dictionary to the mutable array. Release the dictionary and set the ivar to nil. A new dictionary will be created the next time you encounter a #"Description" element in didStartElement:.
If the element name is #"linked-list", the mutable array will contain all the dictionaries and you're done.

problem in copy string for other class

In my app I am sending a request to the web server and getting some results, then I am parsing this result and storing this result string into other class object string.
For example:
#interface GraphView : UIViewController<UITabBarControllerDelegate> {
NSMutableString *graphTempString;
}
#property(nonatomic,retain) NSMutableString *graphTempString;
#end
TSUClass .m
implementing NSURLConnection(),
connectionDidFinishLoading(),
-(void) parser:(NSXMLParser *) parser didStartElement:(NSString *) elementName
namespaceURI:(NSString *) namespaceURI qualifiedName:(NSString *) qName
attributes:(NSDictionary *) attributeDict()
-(void)parser:(NSXMLParser *)parser
didEndElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName
{
if( [elementName isEqualToString:#"statusTEResult"])
{
tempString=soapResults;
if (grpahCall == YES) {
graphViewController=[[GraphView alloc]init];
graphViewController.graphTempString=tempString;
[self.navigationController pushViewController:graphViewController animated:YES];
}
When I am debugging I can see the value of graphViewController.graphTempString but after going to GraphView, I am not able to see the values.
I hope some one know how to solve this issue.
Easy way to pass value.
[[NSUserDefaults standardUserDefaults]setObject:resultString forKey:#"resultString"];
[[NSUserDefaults standardUserDefaults] synchronize];
and in another class use this value like this
NSString *resultString=[[NSUserDefaults standardUserDefaults]valueForKey:#"resultString"];
or u may do it like this.
graphViewController.graphTempString=self.tempString;
can you try
2nClassObj.tempString =[NSString stringWithFormat:#"%#",resultString];
good luck
#Pooja i suggest you to try doing this by making a variable in AppDelegate class give your resultString to this variable and then fetch the value from this variable in your 2ndClass or in any class you want .....you will never get null value.
Lets suppose the object of your AppDelegate class is appDelegate and the variable which of NSString type is lets stringValue. Then in your class where you are getting the resultString do like this.
appDelegate.stringValue = resultString;
And in your 2ndClass class take the value from this variable like this.
tempString = appDelegate.stringValue;
You will get the data.....Hope you got my point.
Good Luck!
What happens if you add some NSLog statements?
if (grpahCall == YES) {
graphViewController=[[GraphView alloc]init];
NSLog(#"-%#-", tempString);
graphViewController.graphTempString=tempString;
NSLog(#"-%#-", graphViewcontroller.graphTempString);
[self.navigationController pushViewController:graphViewController animated:YES];
}
I would expect to see the same thing output twice? Can you tell me what you get in the console?

XMLParsing problem

I display List of date's on my table view....
based on the date's.. i need to search location. and title
"with the help of url".
example
String *url=#"http://compliantbox.com/party_temperature/djsearch.php?date=?"
for the selected date.
i appended the date value to the string url.
So i need to parse again same xml parser. with date search.
<root>
<event title="event_title"location="new york"date="12/01/2011"/>
<event title="event_title2"location="california"date="13/01/2011"/>
<event title="event_title3"location="new york"date="14/01/2011"/>
</root>
here my array get's Re-Initialization.
so i get conflict. when displaying data....
I need to not re-Initialization my array again. and again...
I need to initialize my array only once in entire application.
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName
attributes:(NSDictionary *)attributeDict{
if ([elementName isEqualToString:#"root"]){
dateListArray=[[NSMutableArray alloc] init];
}
}
I Hope you people understand my problem.
Please help me out .
#Thanks to All.
One way that you should trying here,
if([dateListArray count] > 0)
{
[dateListArray removeAllObjects];
[dateListArray release];
}
dateListArray=[[NSMutableArray alloc] init];
And other way you should also be trying,
dateListArray=[[NSMutableArray alloc] init];
above statement write down in -(void)viewDidLoad event and
if([dateListArray count] > 0)
{
[dateListArray removeAllObjects];
}
above write down in your required function.
I guess:
NSMutableArray:-removeAllObjects
may help~

Memory Leak with NSXMLParser on IPhone

below is my code, Leaks says I am getting a memory leak around NSMutableString alloc method. I am sure it is something I simply overlooked, let me know if anyone has any thoughts. Thanks!
-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
if (!currentValue) {
currentValue = [[NSMutableString alloc] initWithCapacity:[string length]];
}
[currentValue setString:[string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]];
}
-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
if([elementName isEqualToString:#"phone"]){
currentAgent.phone = currentValue;
}
[currentValue release];
currentValue = nil;
}
-Agent is a custom object that was created when the class was initialized. The XML is valid and has all the appropriate begin/end tags.
Looking over this code, I think it's more likely that your Agent class is leaking phone. Assuming Agent uses retain for the phone property, this will cause the phone to persist longer than it should.
The creator of the object gets "credited" with the leak, even if the extra retain is somewhere else.
In other words, in Agent:
- (void)dealloc {
self.phone = nil;
// anything else you need to do
[super dealloc];
}