I have an xml like this, but my XMLParser jumps 1-2 elements, and not process it. I think it works fine, but it not. What do i wrong?
Here is the xml, and i'd like to get the all item tag, and it's child elements.
<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>News</title>
<description>News - Android</description>
<link>http://www.p.com</link>
<item>
<title>World Bench Press highlights - Day 2</title>
<pubDate>Tue, 21 May 2013 00:00:00 +0000</pubDate>
<imgLink>http://www.powerlifting-ipf.com/typo3temp/pics/1b7ecb3ac3.jpg</imgLink>
<description>desc </description>
<URL> some URL </URL>
</item>
</channel>
</item>
</rss>
</channel>
Here is my XMLParser file, but i can't get any node, and it not put in my array. Not going to the
if ([elementname isEqualToString:#"item"])
#import <Foundation/Foundation.h>
#import "XMLParser.h"
#implementation XMLParser
#synthesize tweets = _tweets;
NSMutableString *currentNodeContent;
NSMutableString *copy;
NSXMLParser *parser;
Tweet *currentTweet;
bool isStatus=YES;
-(id) loadXMLByURL:(NSString *)urlString
{
_tweets = [[NSMutableArray alloc] init];
NSURL *url = [NSURL URLWithString:urlString];
NSData *data = [[NSData alloc] initWithContentsOfURL:url];
parser = [[NSXMLParser alloc] initWithData:data];
parser.delegate = self;
[parser parse];
NSLog(#"0");
return self;
}
- (void) parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
NSLog(#"1");
NSLog(#"currentnode %#",currentNodeContent);
currentNodeContent = [[NSMutableString alloc] initWithCapacity:100];
[currentNodeContent appendString:string];
}
- (void) parser:(NSXMLParser *)parser didStartElement:(NSString *)elementname namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
NSLog(#"2 Elementname : %#",elementname);
if ([elementname isEqualToString:#"item"])
{
currentTweet = [Tweet alloc];
isStatus = YES;
}
if ([elementname isEqualToString:#"title"])
{
NSLog(#"%#",currentNodeContent);
currentTweet.content = [NSString stringWithFormat:#"%# %#",currentTweet.content ,currentNodeContent];
}
}
- (void) parser:(NSXMLParser *)parser didEndElement:(NSString *)elementname namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
NSLog(#"ELEMENT: %#",elementname);
if ([elementname isEqualToString:#"description"])
{
currentTweet.description = currentNodeContent;
}
if ([elementname isEqualToString:#"pubDate"])
{
currentTweet.dateCreated = currentNodeContent;
}
if ([elementname isEqualToString:#"title"])
{
currentTweet.title = currentNodeContent;
}
if ([elementname isEqualToString:#"imgLink"])
{
currentTweet.imgLink = currentNodeContent;
}
if ([elementname isEqualToString:#"URL"])
{
currentTweet.URL = currentNodeContent;
}
if ([elementname isEqualToString:#"item"])
{
NSLog(#"%# elem:",currentNodeContent);
[self.tweets addObject:currentTweet];
currentTweet = nil;
currentNodeContent = nil;
}
}
#end
Your approach is wrong because you are reallocating your mutable string every time that the XML parser finds new characters. This means that if you get a string like #"Hello", and the strings gets parsed into two separated string #"He" and #"llo", just #"llo" gets put into the mutable string. The correct approach is to allocate a new mutable string every time that you find a new tag, not when you find new characters.
Not sure because I am not aware of the whole context, but I would try to edit your first two methods this way:
- (void) parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
NSLog(#"1");
NSLog(#"currentnode %#",currentNodeContent);
[currentNodeContent appendString:string];
}
- (void) parser:(NSXMLParser *)parser didStartElement:(NSString *)elementname namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
currentNodeContent= [NSMutableString new];
NSLog(#"2 Elementname : %#",elementname);
if ([elementname isEqualToString:#"item"])
{
currentTweet = [Tweet alloc];
isStatus = YES;
}
}
Let me know what result you get. I also recommend putting breakpoints into every method to see (in the case) why you get some particular strings instead of expected results.
Edit
As for the XML, I tried to check it with xmllint, and it some errors. The problem is with these two extra lines after closing the channel tag:
</item> <!-- Not needed -->
</rss>
</channel> <!-- Not needed -->
You have one between and . Maybe that tag could be messing the parse procedure, try deleting it
Related
Newbie to Xcode and would be thrilled to get an answer to this question. I am trying to get the image url tag from a rss feed and add it to my custom table view cell. The other text I get fine.
This is the rss row:
<Item>
<title>this is a title</title>
<description>this is a description</description>
<link>http://www.something.com</link>
<pubDate>Fri, 09 Aug 2013</pubDate>
<enclosure type="image/jpg" url="http://www.ThisIsTheUrlIWant.com" />
</item>
This is part of my code without any image logic:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
CustomCellNews *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
cell.titleLabel.text = [[feeds objectAtIndex:indexPath.row] objectForKey: #"title"];
cell.descriptionLabel.text = [[feeds objectAtIndex:indexPath.row] objectForKey: #"description"];
//set cell image here
return cell;
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI: (NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
element = elementName;
if ([element isEqualToString:#"item"]) {
item = [[NSMutableDictionary alloc] init];
title = [[NSMutableString alloc] init];
link = [[NSMutableString alloc] init];
description = [[NSMutableString alloc] init];
//image stuff
}
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI: (NSString *)namespaceURI qualifiedName:(NSString *)qName {
if ([elementName isEqualToString:#"item"]) {
[item setObject:title forKey:#"title"];
[item setObject:link forKey:#"link"];
[item setObject:description forKey:#"description"];
//image stuff
[feeds addObject:[item copy]];
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
if ([element isEqualToString:#"title"]) {
[title appendString:string];
} else if ([element isEqualToString:#"link"]) {
[link appendString:string];
} else if ([element isEqualToString:#"description"]) {
[ingress appendString:string];
}
//image stuff
}
Thanks
Try this:
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
if ([elementName isEqualToString:#"enclosure"]) {
NSString *units = [attributeDict objectForKey:#"url"];
}
}
Hope this helps.
First get the image URL from the attributes dictionary in the enclosure element inside the didStartElement method:
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
//NSLog(#"Main View: didStartElement: %#\tstart", elementName);
element = elementName;
if ([element isEqualToString:#"item"]) {
item = [[NSMutableDictionary alloc] init];
title = [[NSMutableAttributedString alloc] init];
description = [[NSMutableAttributedString alloc] init];
link = [[NSMutableString alloc] init];
}
if ([element isEqualToString:#"enclosure"]) {
imageType = [attributeDict objectForKey:#"type"];
imageUrl = [attributeDict objectForKey:#"url"];
}
//NSLog(#"RSS Utility: didStartElement: %#", elementName);
}
Then add imageUrl to your item array inside the didEndElement method:
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
if ([elementName isEqualToString:#"item"]) {
[item setObject:title forKey:#"title"];
[item setObject:link forKey:#"link"];
[item setObject:description forKey:#"description"];
[item setObject:imageType forKey:#"imageType"];
[item setObject:imageUrl forKey:#"imageUrl"];
[_feeds addObject:[item copy]];
}
}
This may not work for all rss feeds. I recommend you put NSLog statements inside the didStartElement to understand where the image url can be found:
NSLog(#"\nXML Parser:didStartElement:%#\n\t\t\tnameSpaceURI:%#\n\t\t\tqualifiedName:%#\n\t\t\tattributes:%#", elementName, namespaceURI, qName, attributeDict);
<NewDataSet>
<Table>
<CaseId>743</CaseId>
<PartyId>11100550</PartyId>
<CartId>18</CartId>
</Table>
<Table>
<CaseId>742</CaseId>
<PartyId>11100549</PartyId>
<CartId>1148</CartId>
<BusinessID>19</BusinessID>
</Table>
</NewDataSet>
NSData* data = [xmlResponseData dataUsingEncoding:NSUTF8StringEncoding];
// NSXMLParser *XMLparser = [[NSXMLParser alloc] initWithData:data];
// [XMLparser setDelegate:self];
BOOL success;
if (XMLparser) // addressParser is an NSXMLParser instance variable
[XMLparser release];
XMLparser = [[NSXMLParser alloc] initWithData:data];
[XMLparser setDelegate:self];
[XMLparser setShouldResolveExternalEntities:YES];
success = [XMLparser parse]; // return value not used
// if not successful, delegate is informed of error
if(success)
NSLog(#"Sucess Parsed");
else
NSLog(#"Error Error Error!!!");
// NSLog(#"Parsed string : %#",valueForItem);
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName
attributes:(NSDictionary *)attributeDict {
if([elementName isEqualToString:#"NewDataSet"]) {
caseID_List = [[NSMutableArray alloc]init];
}
NSLog(#"Processing Element: %#", elementName);
if ([elementName isEqualToString:#"CaseId"]) {
}
}
- (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:#"NewDataSet"])
return;
}
I need only CaseId to store from the given xml. Can any one advice me on this simple parsing!
For me its looping! and getting all details
Use the Below Code.Where Table is NSObject Class with the CaseId,PartyId,CartId as a properties in this class.If you have the xml url just called loadXMLByURL method with URl.After parsing you will get Each Object in TableArray which have the Table object with above properties.
NSMutableString *currentNodeContent;
NSXMLParser *parser;
Tweet *currentTweet;
bool isStatus;
-(id) loadXMLByURL:(NSString *)urlString
{
_tweets = [[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:#"Table"])
{
currentTable = [Table alloc];
isStatus = YES;
}
}
- (void) parser:(NSXMLParser *)parser didEndElement:(NSString *)elementname namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if (isStatus)
{
if ([elementname isEqualToString:#"CaseId"])
{
currentTable.CaseId = currentNodeContent;
}
if ([elementname isEqualToString:#"PartyId"])
{
currentTable.PartyId = currentNodeContent;
}
if ([elementname isEqualToString:#"CartId"])
{
currentTable.CartId = currentNodeContent;
}
}
if ([elementname isEqualToString:#"Table"])
{
[self.tableArray addObject:currentTable];
currentTable = nil;
currentNodeContent = nil;
}
}
Let me know if you have any doubt.
XML FILE CODE:
<Books>
<Book id="1" isbn="123456">
<name>Let Us C</name>
<authors>
<author>Yashwant Kanetkar</author>
<author>ABC</author>
</authors>
<price>250.00</price>
</Book>
<Book id="2" isbn="345678">
<name>Programing With C++</name>
<authors>
<author>Balaguruswamy</author>
<author>XYZ</author>
</authors>
<price>400.00</price>
</Book>
<Book id="3" isbn="789012">
<name>Professional iPhone and iPad Application Development</name>
<authors>
<author>Gene Backlin</author>
<author>QWE</author>
</authors>
<price>550.00</price>
</Book>
<Book id="4" isbn="901234">
<name>Beginning iOS 4 Application Development</name>
<authors>
<author>Wei-Meng Lee</author>
<author>IOP</author>
</authors>
<price>500.00</price>
</Book>
</Books>
Can anyone pls help me with this?
I'm using this code:
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict {
if([elementName isEqualToString:#"Books"])
{
appDelegate.books = [[NSMutableArray alloc] init];
}
else if([elementName isEqualToString:#"Book"])
{
aBook = [[Book alloc] init];
aBook.bookID = [[attributeDict objectForKey:#"id"] integerValue];
aBook.isbn = [[attributeDict objectForKey:#"isbn"] integerValue];
NSLog(#"Reading isbn value : %#", aBook.isbn);
NSLog(#"Reading id value :%i", aBook.bookID);
}
NSLog(#"Processing Element: %#", elementName);
}
First take a bool variable. and then write the following code. perhaps it will help you I have done the related work , a few days ago.
First .h file
#interface EventsViewController : UIViewController <NSXMLParserDelegate>
{
NSMutableArray *_idArray;
NSMutableArray *_isbnArray;
BOOL isBook;
}
Then in .m file you should write this.
//In ViewDidLoad
- (void)viewDidLoad
{
[super viewDidLoad];
_idArray = [[NSMutableArray alloc] init];
_isbnArray = [[NSMutableArray alloc] init];
NSString *xmlString = [[NSBundle mainBundle] pathForResource:#"today_in_history_short" ofType:#"xml"];
NSURL * fileURL = [NSURL fileURLWithPath:xmlString];
NSXMLParser * parser = [[NSXMLParser alloc] initWithContentsOfURL:fileURL];
[parser setDelegate:self];
[parser parse];
}
// Now In xml Parser Delegate Methods
pragma mark - NSXMLParser Delegate Method
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{
if ([elementName isEqualToString:#"Books"]) {
isBook = YES;
}
else if ([elementName isEqualToString:#"Book"] && isBook){
NSString *idString = [attributeDict objectForKey:#"id"];
NSString *isbnString = [attributeDict objectForKey:#"isbn"];
[_idArray addObject:idString];
[_isbnArray addObject:isbnString];
NSLog(#"Book id is: %# and Book isbn is: %#",idString,isbnString);
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
if ([elementName isEqualToString:#"Books"]) {
isBook=NO;
NSLog(#"Id Array count is :%d",[_idArray count]);
}
}
Note: I have check it , It's working , you can use it in you code , if still it's won't working then there will be something else wrong in your project, you can verify it by making separate project.
I am following the below link to parse the xml for login page, http://yksoftware.blogspot.in/2010/04/iphone-programming-tutorial-xml-login.html
whenever i enter the fields of username and password, it displays login failed only even when i provide the correct username and password in the textfields.
In the following code when i keep the breakpoint in loginPressed method and check, it is not entering the for loop,
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
users = [[NSMutableArray alloc]init];
NSURL *xmlURL = [NSURL URLWithString:#"http://www.mailrail.net/sample.aspx?username=naresh&password=reddy"];
xmlParser = [[NSXMLParser alloc]initWithContentsOfURL:xmlURL];
[xmlParser setDelegate:self];
[xmlParser parse];
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{
currentElement = [elementName copy];
if ([elementName isEqualToString:#"User"]) {
item = [[NSMutableDictionary alloc] init];
currentUser =[[NSMutableString alloc] init];
currentPassword =[[NSMutableString alloc] init];
}
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
if ([elementName isEqualToString:#"User"]) {
[item setObject:currentUser forKey:#"username"];
[item setObject:currentPassword forKey:#"password"];
[users addObject:[item copy]];
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
if ([currentElement isEqualToString:#"username"]) {
[currentUser appendString:string];
}
if ([currentElement isEqualToString:#"password"]) {
[currentPassword appendString:string];
}
}
-(IBAction)loginPressed:(id)sender{
for (NSMutableDictionary *val in users) {
NSMutableString *usrname = [val objectForKey:#"username"];
NSLog(#"%#",usrname);
NSMutableString *psswrd = [val objectForKey:#"password"];
usrname=[usrname stringByReplacingOccurrencesOfString:#"\n" withString:#""];
usrname=[usrname stringByReplacingOccurrencesOfString:#"\t" withString:#""];
psswrd=[psswrd stringByReplacingOccurrencesOfString:#"\n" withString:#""];
psswrd=[psswrd stringByReplacingOccurrencesOfString:#"\t" withString:#""];
if([usrname isEqualToString:[txtUsername text]]&&[psswrd isEqualToString:[txtPassword text]]){
[lblLoginStatus setText:#"Login Successful!!"];
return;
}
}
[lblLoginStatus setText:#"login failed"];
return;
}
-(IBAction)returnClicked:(UITextField *)sender{
[sender resignFirstResponder];
}
-(IBAction)clickBackground:(id)sender{
[txtPassword resignFirstResponder];
[txtUsername resignFirstResponder];
}
and returns with login failed.
Thanks in advance.
You first need to solve the parsing how to parse some thing from xml using parser and then think for loging beacuse if you have made parser then it is easy to use login form. Below is the following tutorial for XML parsing it is detailed and help you can get help.
http://www.edumobile.org/iphone/iphone-programming-tutorials/parsing-an-xml-file/
hope this helps
Just check this
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{
currentElement = [elementName copy];
if ([elementName isEqualToString:#"User"]) {
NSMutableDictionary *item = [[NSMutableDictionary alloc] init];
[item setValue:[attributeDict valueForKey:#"username"] forKey:#"username"];
[item setValue:[attributeDict valueForKey:#"password"] forKey:#"password"];
[users addObject:item];
}
}
please del other two delegates and check this
How to parse a locally stored XML file in iPhone?
please help me with this using code snippets
I have used NSXMLParser and i achieved it. I have r.xml file in my resource. I have just parsing the title and displayed using NSXMLParser.
r.xml:
<rss>
<eletitle > My Xml Program </eletitle>
</rss>
Here my sample code is,
#interface:
NSXMLParser *rssparser;
NSMutableArray *stories;
NSMutableDictionary *item;
NSMutableString *currrentTitle;
NSString *currentElement;
#implementation:
-(void) viewDidAppear:(BOOL) animated
{
[self parseXMLFileAtURL];
}
-(void) parseXMLFileAtURL
{
stories = [[NSMutableArray alloc] init];
NSURL *xmlURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:#"r" ofType:#"xml"]];
rssparser = [[NSXMLParser alloc] initWithContentsOfURL:xmlURL];
[rssparser setDelegate:self];
[rssparser setShouldProcessNamespaces:NO];
[rssparser setShouldReportNamespacePrefixes:NO];
[rssparser setShouldResolveExternalEntities:NO];
[rssparser parse];
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{
currentElement = [elementName copy];
if([elementName isEqualToString:#"rss"]);
{
item = [[NSMutableDictionary alloc] init];
currrentTitle = [[NSMutableString alloc] init];
}
}
-(void) parser:(NSXMLParser *)parser foundCharacters:(NSString *) string
{
if([currentElement isEqualToString:#"eletitle"])
{
[currrentTitle appendString:string];
}
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
if([elementName isEqualToString:#"rss"])
{
[item setObject:currrentTitle forKey:#"eletitle"];
[stories addObject:[item copy]];
}
}
- (void)parserDidEndDocument:(NSXMLParser *)parser
{
NSLog(#"The currrentTitle is %#",currrentTitle);
}
Best of Luck.
I'm sorry I cannot give you any snippet now, but in one project I did some time ago, we used the touchXML library.
http://code.google.com/p/touchcode/wiki/TouchXML
With this, parsing XML was pretty easy.
Good luck!