Parsing xml to objective-c - objective-c

i'm trying to parse an xml document into 2 NSMutableArrays, but it seems like it is overwriting my array. my xml doc contain 3 objects, but my array only contain 1. Why does it overwrite the previous added objects from the xml doc?
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict{
if ([elementName isEqualToString:#"playlist"]) {
title = [attributeDict valueForKey:#"title"];
listid = [[attributeDict valueForKey:#"id"] intValue];
lists = [[NSMutableArray alloc]init];
lists2 = [[NSMutableArray alloc]init];
[lists addObject:title];
[lists2 addObject:[NSString stringWithFormat:#"%d", listid]];
}
NSLog(#"%d", lists.count);
}
xml doc:
<?xml version="1.0"?>
<Lists>
<playlist title="Quo Vadis" id="0"/>
<playlist title="Lord of the Rings" id="1"/>
<playlist title="Face" id="2"/>
</Lists>

You assign a new (empty) array to lists and lists2 each time in didStartElement,
and therefore overwrite what was previously in those variables.
The arrays must be created only once, before you start the parse method.

Related

Decode percent escaped string inside NSXMLParser delegate method

i'm getting a UTF8 encoded data from a server data is like Less%20than%20100 but i need this data in Less than 100 (decoded format),my NSXMLParsing delegate method is like
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName
attributes:(NSDictionary *)attributeDict {
if([elementName isEqualToString:#"option"]) {
dict = [[NSMutableDictionary alloc]init];
[dict setValue:[attributeDict objectForKey:#"text"] forKey:#"text"];/* Here itself i need to decode & save in to my dict */
}
How to decode this data.
After you have decoded your xml, use stringByReplacingPercentEscapesUsingEncoding: method on NSString :
NSString *decoded = [text stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
See the docs here.

count elements in xml using objective c

I've got an XML file and I need to count how many times the element appears in it using Objective-C. How should I do this?
<?xml version="1.0" encoding="ISO-8859-1"?>
<residents>
<resident id="1">
<name>
<first>David</first>
<last>Dollar</last>
</name>
</resident>
<resident id="2">
<name>
<first>Michael</first>
<last>Nipp</last>
</name>
</resident>
etc...
I would set your class as the delegate of the parser, then this class will receive parse events such as parser:didStartElement:, parser:foundCharacters: and parser:didEndElement:.
self.parser = [[NSXMLParser alloc] initWithData:xmlData];
[self.parser setDelegate:self];
[self.parser parse];
I would create a count variable in your parser delegate. Anytime an element is found, the didStartElement: function is called on the parser delegate. Check if it's the "resident" element and increment the count if so.
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
if ([elementName isEqualToString:#"resident"]) {
self.count += 1;
}
}

XML parsing in IOS Shows NULL value in label?

i m doing XML parsing using NSXMLParserDelegate..I m getting null value when i print the value in label...I m using simple xml file got in an internet.You can check what is in that file too.anyone pls help..Here is my code
#import "xmlViewController.h"
#implementation xmlViewController
#synthesize label;
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
NSURL *url=[NSURL URLWithString:[NSString stringWithFormat:#"http://www.bonifacedesigns.com/tuts/xmltest.xml"]];
receivedData=[[NSMutableData alloc]initWithContentsOfURL:url];
dataParser=[[NSXMLParser alloc]initWithData:receivedData];
dataParser.delegate=self;
[dataParser parse];
}
-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{
// if(!xmlString){
//
// }else
// {
// [xmlString setString:#""];
// }
if([elementName isEqualToString:#"elements"])
{
xmlString=[NSMutableString alloc];
[xmlString setString:#""];
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
xmlString= (NSMutableString *)[string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
}
-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if([elementName isEqualToString:#"element"]){
NSString *string=xmlString;
[xmlArray addObject:string];
label.text=[NSString stringWithFormat:#"%#",xmlArray];
}
}
#end
This is my XML file....I want to print XML Data Parsed! in my label.Help me with that.I have edited the code and check now
<elements>
<element myData="XML Data Parsed!"/>
</elements>
check this:
-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{
// if(!xmlString){
//
// }else
// {
// [xmlString setString:#""];
// }
if([elementName isEqualToString:#"elements"])
{
xmlString=[[NSMutableString alloc]initWithCapacity:5];
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
xmlString= (NSMutableString *)[string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
}
-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if([elementName isEqualToString:#"element"]){
[attributeDict objectForKey:#"myData"];
[xmlString setString:#""];
NSString *string=xmlString;
[xmlArray addObject:string];
label.text=[NSString stringWithFormat:#"%#",xmlArray];
}
I m getting error:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Attempt to mutate immutable object with setString:'
*** First throw call stack:
(0x13ba052 0x154bd0a 0x1362a78 0x13629e9 0x1387970 0x2a26 0x9e1a35 0x5171532 0x9e002d 0x26b8 0xd764e 0x37a73 0x37ce2 0x37ea8 0x3ed9a 0xfbe6 0x108a6 0x1f743 0x201f8 0x13aa9 0x12a4fa9 0x138e1c5 0x12f3022 0x12f190a 0x12f0db4 0x12f0ccb 0x102a7 0x11a9b 0x2238 0x2195 0x1)
terminate called throwing an exception
It seems you have several errors in your code.
The mutable string xmlString isn't properly initialized, on the line :
xmlString = [NSMutableString alloc]; // wrong
This should look like : xmlString = [[NSMutableString alloc] initWithCapacity:X];.
Also, when the parser finds characters, you replace the entire existing mutable string, instead of appending them to the existing content, or try to because according to the code, you simply make a memory address compare and waste the result (==).
// wrong
xmlString == (NSMutableString *)[string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
This should look like :
[xmlString appendString:[string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]];
Finally in didEndElement, I'm not sure what you are trying to achieve, but you add the string object reference to an array, and then set the label text to display the content of the array... as long as the mutable array is well allocated and initialized (what I'm really not sure), the label should display at least the array content. But you might consider to "flush" the mutable string ([xmlString setString:#""];) and not allocate it on every element.
EDIT :
The attributeDict maps attribute names as the keys with their values. I guess your attribute value can be accessed via [attributeDict objectForKey:#"myData"];.
I guess that the problem is in this line:
xmlString== (NSMutableString *)[string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
Change == to =
Hope that explanation isn't needed.

How to load XML file data into a UITableView?

I am retrieving an XML document from a server and would like to display it in a UITableView in my application. I have the following code so far:
#implementation textxmlViewController
#synthesize tableviews;
-(void)viewDidLoad{
[super viewDidLoad];
NSURL *url = [[NSURL alloc] initWithString:#"http://theserver.com/demo.xml"];
NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithContentsOfURL:url];
[xmlParser setDelegate:self];
BOOL success = [xmlParser parse];
if(success)
NSLog(#"success");
else
NSLog(#"Error");
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
NSLog(string);
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
if (qName) {
elementName = qName;
}
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
attributes:(NSDictionary *)attributeDict {
if (qName) {
elementName = qName;
}
if ([elementName isEqualToString:#"text"]) {
}
}
I already have a UITableView in this view, my question is how can I display the XML's content in the table view?
My XML data looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<Answers>
<Answer>
<Result>it's good</Result>
<Evaluate>can you tell me why?</Evaluate>
</Answer>
<Answer>
<Result>about 5 hours</Result>
<Evaluate>it's too long</Evaluate>
</Answer>
</Answers>
So how can I do it? Thanks
I would recommend to use another XML parser instead of using NSXMLParser.
Ray Wenderlich wrote a good article about the different XML parsing possibilities on the iPhone(iOS): http://www.raywenderlich.com/553/how-to-chose-the-best-xml-parser-for-your-iphone-project
I think it'd be easier for you using a DOM based XML parser. you could use the indexPath to get the data right out of the parsed xmlData.
For example: if your using GDataXML you just need to call the method
+ (GDataXMLElement *)elementsWithName:(NSString *)name;
with name = 'Answers' which returns the Node for all the answer.
on this GDataXMLElement call the method
- (NSArray *)elementsForName:(NSString *)name;
with name = 'Answer' which gives you all the answers as a NSArray.
You can use this array as datasource for you UITableView by returning numberOfRowsInSection with [answersArray count]. And in the cellForIndexPath method get the GDataXMLElement for the answer by calling
GDataXMLElement * answerElement = [answersArray objectAtIndex: indexPath.row];
Just parse the answerElement for the elements 'name' and 'value' to show the data in your UITableView.
It depends on how you want the info to be displayed. At least you should implement cellForRowAtIndexPath: to return the UITableViewCell to be displayed.
According to your XML structure, you can have cells for answers, each having two UITextFields to display the result and evaluate.
Please take a look at http://adeem.me/blog/2009/05/19/iphone-programming-tutorial-part-1-uitableview-using-nsarray/ for a tutorial.

NSMutableString issue with NSXMLParser

I am having a heck of a time with this -- I am trying to parse an XML file and set the text in a NSMutableString variable in order to later fill in a label's text as you can see below.
In my .h I have the following (simplified);
NSMutableString *contentsOfCurrentXMLProperty;
#property (nonatomic,retain) NSMutableString *contentsOfCurrentXMLProperty;
In my .m:
-(void) parseData {
NSXMLParser *parser = [[NSXMLParser alloc] initWithData:myData];
[parser setDelegate:self];
[parser parse];
[parser release];
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
if ([elementName isEqualToString:#"Title"]) {
NSLog(#"FOUND TITLE!");
contentsOfCurrentXMLProperty = [NSMutableString setString:#""];
}
}
-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
if ([elementName isEqualToString:#"TITLE"]) {
myLabel.text = [contentsOfCurrentXMLProperty stringByReplacingOccurrencesOfString:#"[br]" withString:#"\n"];
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
[self.contentsOfCurrentXMLProperty appendString:string];
}
When I run my app, the data is downloaded and parsed correctly. I run into issues when my observer fires off the event again. The parseData method is called and I get an error that I have traced to the line that reads: "contentsOfCurrentXMLProperty = [NSMutableString setString:#""];
"
What is the proper way to create or init a NSMutableString variable for me to use over and over? When/Where is the best place to release it? How do I essentially clear the variable so that when the observer fires off the parseData method it will again be able to set "contentsOfCurrentXMLProperty"?
-setString: is an instance method, not a class method. If you already have a valid NSMutableString object assigned to contentsOfCurrentXMLProperty and simply want to clear it, then:
contentsOfCurrentXMLProperty = [NSMutableString setString:#""];
should be
[contentsOfCurrentXMLProperty setString:#""];
On the other hand, if you want to assign a new object to contentsOfCurrentXMLProperty, here's one valid way to do it:
self.contentsOfCurrentXMLProperty = [NSMutableString stringWithCapacity:0];