Its my first experience with xmls so please don't be harsh on me if my question is low quality. I am working on app where I retrieve all data using xml files from server.
Before posting question here I read some Tutorials about xml file parsing. But when I start to implement it in my app, then I am totally confused at the point when I am trying to parse the second Xml file and so on.
Now I want to explain my app flow using some screenshot so that it become easy for everyone that what I want.
First view
Second view
Third view
Now when I click in any row in first view it goes to second view and show all related data in second view and when I click any item in Second view it goes to the third view and show detail information about that particular item.
After explanation of app flow, now I show my code what I tried so far. Following a tutorial I just simply drag classes (XMLParser, Book) to my app for testing purpose.
Code:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSURL *url = [[NSURL alloc] initWithString:#"Firstviewxmlurl"];
NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithContentsOfURL:url];
XMLParser *parser = [[XMLParser alloc] initXMLParser];
[xmlParser setDelegate:parser];
BOOL success = [xmlParser parse];
if(success)
NSLog(#"No Errors");
else
NSLog(#"Error Error Error!!!");
}
Now my XMLParser.m code is
- (XMLParser *) initXMLParser {
[super init];
appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
return self;
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName
attributes:(NSDictionary *)attributeDict {
if([elementName isEqualToString:#"Collections"]) {
//Initialize the array.
appDelegate.books = [[NSMutableArray alloc] init];
}
else if([elementName isEqualToString:#"Collection"]) {
//Initialize the book.
aBook = [[Book alloc] init];
//Extract the attribute here.
aBook.bookID = [[attributeDict objectForKey:#"id"] integerValue];
NSLog(#"Reading id value :%i", aBook.bookID);
}
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:#"Collections"])
return;
if([elementName isEqualToString:#"Collection"]) {
[appDelegate.books addObject:aBook];
[aBook release];
aBook = nil;
}
else
[aBook setValue:currentElementValue forKey:elementName];
[currentElementValue release];
currentElementValue = nil;
}
Finaly my First view Class code is
#pragma mark Table Methods
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
//return [tblViewData count];
return [appDelegate.books count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"SimpleTableIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell=[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier];
cell.selectionStyle=UITableViewCellSelectionStyleGray;
cell.accessoryType=UITableViewCellAccessoryDisclosureIndicator;
}
//cell.textLabel.text=[[tblViewData objectAtIndex:indexPath.row]
// stringByReplacingOccurrencesOfString:#"*" withString:#""];
Book *aBook = [appDelegate.books objectAtIndex:indexPath.row];
cell.textLabel.text = aBook.title;
if([deviceType isEqualToString:#"ipad"])
{
[cell.textLabel setFont:[UIFont fontWithName:#"Helvetica-Bold" size:20]];
}
//cell.textLabel.font=[UIFont fontWithName:#"Walkway_SemiBold" size:16];
return cell;
}
After implementation of all the above Code i got the result in form of this Now at this point i confuse how can i pass my Second view xml file url and then third view url.my xml files are in this format
First xml file
<?xml version="1.0" encoding="UTF-8"?>
<Collections> <Collection id="5"><title>Allegroo</title> </Collection>
Second xml file
<?xml version="1.0" encoding="UTF-8"?>
<Collection id="5"><colletciontitle>Allegroo</colletciontitle> <weaveimage>"imageurl" </weaveimage><Rug id="48"><Rugthumb>"firstimageurl"</Rugthumb><RugSku>AL-637</RugSku></Rug><Rug id="51"><Rugthumb>"Secondimageurl"</Rugthumb><RugSku>AL-641</RugSku></Rug>
Third xml file
<?xml version="1.0" encoding="UTF-8"?>
<Rug id="47"><Rugmainimage>"imageurl"</Rugmainimage> <Rugtitle>AL-636 Aged Indigo / Vintage Beige</Rugtitle> <Rugdiscription>Hand Knotted
Distressed Wool Pile / Cotton Foundation </Rugdiscription><Availablesizes><Size>10x14</Size><Size>12x15</Size><Size>2x3</Size><Size>3x5</Size><Size>4x6</Size><Size>6x9</Size><Size>8x10</Size><Size>9x12</Size><Runner>2'6"x10'</Runner><Runner>2'6"x12'</Runner><Runner>2'6"x8'</Runner></Availablesizes></Rug>
Any help in the form of link or sample code releated to my issue and suggestion will be highly appriated.Thanks
Hmm, So Defining long story short, you want to parse multiple urls in sequence ?
So here is the answer,
Use a variable / identifier in appDelegate that tells you which xml is being parsed.
Use your xml parser as delegate class object
Use delegate method to swich to next xml parsing
- (void)parserDidEndDocument:(NSXMLParser *)parser {
// Change URL accordingly
NSURL *url = [[NSURL alloc] initWithString:#"Firstviewxmlurl"];
NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithContentsOfURL:url];
XMLParser *parser = [[XMLParser alloc] initXMLParser];
[xmlParser setDelegate:parser];
BOOL success = [xmlParser parse];
}
I have added some of the code to make you understand. Try to implement according to your condition. Below code is just to refer as i havn't made all the changes u need to understand first and then implement accordingly
//int i = 0; // in AppDelegate
Code:
//Or ViewDidLoad Method
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
int = 1; //For First View
NSURL *url = [[NSURL alloc] initWithString:#"Firstviewxmlurl"];
NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithContentsOfURL:url];
XMLParser *parser = [[XMLParser alloc] initXMLParser];
[xmlParser setDelegate:parser];
BOOL success = [xmlParser parse];
if(success)
NSLog(#"No Errors");
else
NSLog(#"Error Error Error!!!");
}
XMLParser.m
- (XMLParser *) initXMLParser
{
[super init];
appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
return self;
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName
attributes:(NSDictionary *)attributeDict {
if([elementName isEqualToString:#"Collections"])
{
//Initialize the array.
if (int == 1)
appDelegate.books = [[NSMutableArray alloc] init];
else if (int == 2)
appDelegate.secondArray = [[NSMutableArray alloc] init];
else if (int == 3)
appDelegate.thirdArray = [[NSMutableArray alloc] init];
}
else if([elementName isEqualToString:#"Collection"])
{
if (i == 1)
{
//Initialize the book.
aBook = [[Book alloc] init];
//Extract the attribute here.
aBook.bookID = [[attributeDict objectForKey:#"id"] integerValue];
NSLog(#"Reading id value :%i", aBook.bookID);
}
else if (i == 2)
{
//Second Xml
}
else if (i == 3)
{
//Third Xml
}
}
NSLog(#"Processing Element: %#", elementName);
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
//Check condition
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 {
//Check COndition
if([elementName isEqualToString:#"Collections"])
return;
if([elementName isEqualToString:#"Collection"]) {
[appDelegate.books addObject:aBook];
[aBook release];
aBook = nil;
}
else
[aBook setValue:currentElementValue forKey:elementName];
[currentElementValue release];
currentElementValue = nil;
}
Related
I am able to parse the xml data and able to display it in the console, but not able to display that data in the UITextField or in UILabel.
I tried to assign to textfield in the viewDidLoad method also.
The following is my code,
NSMutableString *currentNodeContent;
NSXMLParser *parser;
ViewController *currentProfile;
bool isStatus;
ViewController *xmlParser;
-(id)loadXMLByURL:(NSString *)urlString
{
_profile = [[NSMutableArray alloc] init];
NSURL *url = [NSURL URLWithString:urlString];
NSData *data = [[NSData alloc] initWithContentsOfURL:url];
parser = [[NSXMLParser alloc] initWithData:data];
parser.delegate = self;
[parser parse];
return self;
}
-(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:#"profileinfo"])
{
currentProfile = [ViewController alloc];
isStatus = YES;
}
if([elementName isEqualToString:#"first_name"])
{
currentProfile = [ViewController alloc];
isStatus = YES;
}
}
-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if([elementName isEqualToString:#"first_name"])
{
currentProfile.firstName = currentNodeContent;
NSLog(#"%#",currentProfile.firstName);
first_Name.text = currentNodeContent;//UITextField
first_name.text = currentNodeContent;//Label
}
if([elementName isEqualToString:#"last_name"])
{
currentProfile.lastName = currentNodeContent;
NSLog(#"%#",currentProfile.lastName);
last_Name.text = currentProfile.lastName;
}
if([elementName isEqualToString:#"profileinfo"])
{
[self.profile addObject:currentProfile];
currentProfile = nil;
currentNodeContent = nil;
}
}
- (void)viewDidLoad
{
[super viewDidLoad];
xmlParser = [[ViewController alloc] loadXMLByURL:#"http://www.mxxxxx.net/xxx/xxxxx.aspx?type=proifileinfo&loginid=xxx#gmail.com"];
}
Instead of assigning the values directly to the 'UITextField' or 'UILabel', have the values stored in a string. And when the parsing action completed, assign the string value to the 'UITextField' or 'UILabel'; Probably you should do that in '-viewWillAppear' method :-)
Create a IBOutlet UILabel *label; in the interface, connect it in Interface Builder, and then you can set the text of it by label.text = #"Anything";
I have also the same problem while parsing XML parser.
currentNodeContent = (NSMutableString *) [string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
}
You are using the above line to trim spaces and tabs. But sometimes It does not work.
So, I implement the following code. The code may be useful to you.
NSString *sname = [currentNodeContent stringByReplacingOccurrencesOfString:#"\n" withString:#""];
NSString *actualString = [sname stringByReplacingOccurrencesOfString:#"\t" withString:#""];
Then pass the actualString to whatever you required.
I'm following a tutorial and it's working fine but if I wanted to parse 2 RSS feeds it seems to overwrite one array instead of saving them in the respective arrays.
This is in my delegate:
NSURL *url2 = [[NSURL alloc] initWithString:#"myRSSFEED1"];
NSXMLParser *xmlParser1 = [[NSXMLParser alloc] initWithContentsOfURL:url2];
//Initialize the delegate.
XMLParser1 *parser1 = [[XMLParser1 alloc] initXMLParser];
//Set delegate
[xmlParser1 setDelegate:parser1];
//Start parsing the XML file.
BOOL successs = [xmlParser1 parse];
if(successs)
NSLog(#"No Errors");
else
NSLog(#"Error Error Error!!!");
//VIDS
NSURL *url = [[NSURL alloc] initWithString:#"MYRSSFEED2"];
NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithContentsOfURL:url];
//Initialize the delegate.
XMLParser *parser = [[XMLParser alloc] initXMLParser];
//Set delegate
[xmlParser setDelegate:parser];
//Start parsing the XML file.
BOOL success = [xmlParser parse];
if(success)
NSLog(#"No Errors");
else
NSLog(#"Error Error Error!!!");
that parses feed 1, allocates it to the array then parses 2 and seems to overwrite the first insteaf of using the second array that are defined as
#synthesize pics;
#synthesize books;
And saved in my XMLParser & XMLParser1
I can't figure out how to stop it from overwriting.
Here is my XMLParsers too:
- (void)parsers:(NSXMLParser *)parsers didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName
attributes:(NSDictionary *)attributeDict {
if([elementName isEqualToString:#"Books"]) {
//Initialize the array.
appDelegate2.pics = [[NSMutableArray alloc] init];
}
else if([elementName isEqualToString:#"Book"]) {
//Initialize the book.
apics = [[BookPhoto alloc] init];
//Extract the attribute here.
apics.bookID = [[attributeDict objectForKey:#"id"] integerValue];
NSLog(#"Reading HAVid value :%i", apics.bookID);
}
NSLog(#"Processing Element: %#", elementName);
}
- (void)parsers:(NSXMLParser *)parsers foundCharacters:(NSString *)string {
if(!currentElementValue)
currentElementValue = [[NSMutableString alloc] initWithString:string];
else
[currentElementValue appendString:string];
NSLog(#"Processing Value: %#", currentElementValue);
}
- (void)parsers:(NSXMLParser *)parsers didEndElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
if([elementName isEqualToString:#"Books"])
return;
//There is nothing to do if we encounter the Books element here.
//If we encounter the Book element howevere, we want to add the book object to the array
// and release the object.
if([elementName isEqualToString:#"Book"]) {
[appDelegate2.pics addObject:apics];
[apics release];
apics = nil;
}
else
[apics setValue:currentElementValue forKey:elementName];
[currentElementValue release];
currentElementValue = nil;
}
And my XMLParser.m
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName
attributes:(NSDictionary *)attributeDict {
if([elementName isEqualToString:#"Books"]) {
//Initialize the array.
appDelegate.books = [[NSMutableArray alloc] init];
}
else if([elementName isEqualToString:#"Book"]) {
//Initialize the book.
aBook = [[Book alloc] init];
//Extract the attribute here.
aBook.bookID = [[attributeDict objectForKey:#"id"] integerValue];
NSLog(#"Reading id value :%i", aBook.bookID);
}
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:#"Books"])
return;
//There is nothing to do if we encounter the Books element here.
//If we encounter the Book element howevere, we want to add the book object to the array
// and release the object.
if([elementName isEqualToString:#"Book"]) {
[appDelegate.books addObject:aBook];
[aBook release];
aBook = nil;
}
else
[aBook setValue:currentElementValue forKey:elementName];
[currentElementValue release];
currentElementValue = nil;
}
Any help on this would be brilliant,
I suggest putting a breakpoint at the point where the array is not getting loaded, and seeing if (1) it even gets called, and (2), whether it is saving the data into the array at all.
my bad
seems i had extra s's in parser:
- (void)parsers:(NSXMLParser *)parsers foundCharacters:(NSString *)string {
if(!currentElementValue)
currentElementValue = [[NSMutableString alloc] initWithString:string];
else
[currentElementValue appendString:string];
NSLog(#"Processing Value: %#", currentElementValue);
}
should have been:
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
if(!currentElementValue)
currentElementValue = [[NSMutableString alloc] initWithString:string];
else
[currentElementValue appendString:string];
NSLog(#"Processing Value: %#", currentElementValue);
}
cheers for the help tho
I'm a newbie to Objective-C & iPhone development, hence please bear with me.
I'm working on an app which loads with UITableView and upon selecting one particular cell called "Address Book" it should load with another UITableView containing all the addresses retrieved from a web request. Using NSXMLParser's delegate methods I'm storing those addresses into a NSMutableArray defined in the loaded view's header file. But the problem occurs when those addresses are being displayed onto the UITableView cells (yes, I have got the count for the number of cells). Can anybody please help me with this problem? I'm stuck on this for days now !!! Following is my code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
AddressEntry *entry = (AddressEntry *)[self.addresses objectAtIndex:indexPath.row];
#try
{
NSLog(#"%#", entry.firstName);
}
#catch (NSException * e)
{
#try
{
NSLog(#"%#", entry.lastName);
}
#catch (NSException * e)
{
NSLog(#"%#", entry.lastName);
}
}
[entry release];
return cell;
}
- (void)parserDidStartDocument:(NSXMLParser *)parser
{
self.currentElement = nil;
self.f_Name = nil;
self.l_Name = nil;
self.phone = nil;
self.email = nil;
count = 0;
self.addresses = [[NSMutableArray alloc] init];
}
- (void) parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName
attributes:(NSDictionary *)attributeDict
{
if([elementName isEqualToString:#"Entries"])
{
count = [[attributeDict valueForKey:#"total"] intValue];
}
else if([elementName isEqualToString:#"FirstName"])
{
[self.f_Name release];
self.f_Name = [[NSString alloc] init];
}
else if([elementName isEqualToString:#"LastName"])
{
[self.l_Name release];
self.l_Name = [[NSString alloc] init];
}
else if([elementName isEqualToString:#"PhoneNumber"])
{
[self.phone release];
self.phone = [[NSString alloc] init];
}
else if([elementName isEqualToString:#"EmailAddress"])
{
[self.email release];
self.email = [[NSString alloc] init];
}
else if([elementName isEqualToString:#"Record"])
{
[self.addrEntry release];
self.addrEntry = [[[AddressEntry alloc] init] retain];
}
[self.currentElement release];
self.currentElement = nil;
self.currentElement = [elementName copy];
}
- (void) parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName
{
//
if([elementName isEqualToString:#"FirstName"])
self.addrEntry.firstName = self.f_Name;
else if ([elementName isEqualToString:#"LastName"])
self.addrEntry.lastName = self.l_Name;
else if([elementName isEqualToString:#"PhoneNumber"])
self.addrEntry.mobile = self.phone;
else if([elementName isEqualToString:#"EmailAddress"])
self.addrEntry.emailAddress = self.email;
else if([elementName isEqualToString:#"Record"])
{
[self.addresses addObject:self.addrEntry];
[self.addrEntry release];
self.addrEntry = nil;
/*AddressEntry *e = (AddressEntry *)[self.addresses lastObject];
NSLog(#"%# %# %# %#", e.firstName, e.lastName, e.mobile, e.emailAddress);
[e release];*/
}
}
- (void) parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
if([currentElement isEqualToString:#"FirstName"])
self.f_Name = string;
else if([currentElement isEqualToString:#"LastName"])
self.l_Name = string;
else if([currentElement isEqualToString:#"PhoneNumber"])
self.phone = string;
else if([currentElement isEqualToString:#"EmailAddress"])
{
self.email = string;
}
}
The most likely reason for the app crashing is this line in cellForRowAtIndexPath:
[entry release];
You did not alloc/init the variable entry there so don't call release on it. Remove that line.
In that method, entry is only holding a reference to an already-allocated object in the address array. It doesn't "own" the object so it shouldn't release it.
This page in the Apple docs shows a nice flow diagram and some simple rules for memory management that might help in understanding this better.
As a separate issue unrelated to the crashing, the use of #try/#catch in your example seems unnecessary. See this answer for an explanation.
Finally, also unrelated to the crashing, in foundCharacters, you should really be appending the string parameter to your data instead of just assigning because it's possible for that method to be called multiple times within the same value. See Handling XML Elements and Attributes for an example.
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).
Okay i have seen TouchXML, parseXML, NSXMLDocument, NSXMLParser but i am really confused with what to to do.
I have an iphone app which connects to a servers, requests data and gets XML response. Sample xml response to different set of queries is give at http://pastebin.com/f681c4b04
I have another classes which acts as Controller (As in MVC, to do the logic of fetch the data). This class gets the input from the View classes and processes it e.g. send a request to the webserver, gets xml, parses xml, populates its variables (its a singleton/shared Classes), and then responses as true or false to the caller. Caller, based on response given by the controller class, checks controller's variables and shows appropriate contents to the user.
I have the following Controller Class variables:
#interface backendController : NSObject {
NSMutableDictionary *searchResults, *plantInfoResults, *bookmarkList, *userLoginResult;
}
and functions like getBookmarkList, getPlantInfo. Right now i am printing plain XML return by the webserver by
NSLog(#"Result: :%#" [NSString stringWithContentsOfURL:url])
I want a generic function which gets the XML returned from the server, parseses it, makes a NSMutableDictionary of it containing XML opening tags' text representation as Keys and XML Tag Values as Values and return that.
Only one question, how to do that?.
Have you tried any of the XML Parsers you mentioned? This is how they set the key value of a node name:
[aBook setValue:currentElementValue forKey:elementName];
P.S. Double check your XML though, seems you are missing a root node on some of your results. Unless you left it out for simplicity.
Take a look at w3schools XML tutorial, it should point you in the right direction for XML syntax.
Consider the following code snippet, that uses libxml2, Matt Gallagher's libxml2 wrappers and Ben Copsey's ASIHTTPRequest to parse an HTTP document.
To parse XML, use PerformXMLXPathQuery instead of the PerformHTTPXPathQuery I use in my example.
The nodes instance of type NSArray * will contain NSDictionary * objects that you can parse recursively to get the data you want.
Or, if you know the scheme of your XML document, you can write an XPath query to get you to a nodeContent or nodeAttribute value directly.
ASIHTTPRequest *request = [ASIHTTPRequest alloc] initWithURL:[NSURL URLWithString:#"http://stackoverflow.com/"];
[request start];
NSError *error = [request error];
if (!error) {
NSData *response = [request responseData];
NSLog(#"Root node: %#", [[self query:#"//" withResponse:response] description]);
}
else
#throw [NSException exceptionWithName:#"kHTTPRequestFailed" reason:#"Request failed!" userInfo:nil];
[request release];
...
- (id) query:(NSString *)xpathQuery withResponse:(NSData *)respData {
NSArray *nodes = PerformHTMLXPathQuery(respData, xpathQuery);
if (nodes != nil)
return nodes;
return nil;
}
providing you one simple example of parsing XML in Table, Hope it would help you.
//XMLViewController.h
#import <UIKit/UIKit.h>
#interface TestXMLViewController : UIViewController<NSXMLParserDelegate,UITableViewDelegate,UITableViewDataSource>{
#private
NSXMLParser *xmlParser;
NSInteger depth;
NSMutableString *currentName;
NSString *currentElement;
NSMutableArray *data;
}
#property (nonatomic, strong) IBOutlet UITableView *tableView;
-(void)start;
#end
//TestXMLViewController.m
#import "TestXmlDetail.h"
#import "TestXMLViewController.h"
#interface TestXMLViewController ()
- (void)showCurrentDepth;
#end
#implementation TestXMLViewController
#synthesize tableView;
- (void)start
{
NSString *xml = #"<?xml version=\"1.0\" encoding=\"UTF-8\" ?><Node><name>Main</name><Node><name>first row</name></Node><Node><name>second row</name></Node><Node><name>third row</name></Node></Node>";
xmlParser = [[NSXMLParser alloc] initWithData:[xml dataUsingEncoding:NSUTF8StringEncoding]];
[xmlParser setDelegate:self];
[xmlParser setShouldProcessNamespaces:NO];
[xmlParser setShouldReportNamespacePrefixes:NO];
[xmlParser setShouldResolveExternalEntities:NO];
[xmlParser parse];
}
- (void)parserDidStartDocument:(NSXMLParser *)parser
{
NSLog(#"Document started");
depth = 0;
currentElement = nil;
}
- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError
{
NSLog(#"Error: %#", [parseError localizedDescription]);
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName
attributes:(NSDictionary *)attributeDict
{
currentElement = [elementName copy];
if ([currentElement isEqualToString:#"Node"])
{
++depth;
[self showCurrentDepth];
}
else if ([currentElement isEqualToString:#"name"])
{
currentName = [[NSMutableString alloc] init];
}
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName
{
if ([elementName isEqualToString:#"Node"])
{
--depth;
[self showCurrentDepth];
}
else if ([elementName isEqualToString:#"name"])
{
if (depth == 1)
{
NSLog(#"Outer name tag: %#", currentName);
}
else
{
NSLog(#"Inner name tag: %#", currentName);
[data addObject:currentName];
}
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
if ([currentElement isEqualToString:#"name"])
{
[currentName appendString:string];
}
}
- (void)parserDidEndDocument:(NSXMLParser *)parser
{
NSLog(#"Document finished", nil);
}
- (void)showCurrentDepth
{
NSLog(#"Current depth: %d", depth);
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
data = [[NSMutableArray alloc]init ];
[self start];
self.title=#"XML parsing";
NSLog(#"string is %#",data);
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
`enter code here`return [data count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
cell.textLabel.text = [data objectAtIndex:indexPath.row];
return cell;
}
#end