So I am making an app that one part of it displays the users tweets in a table view. However there's something getting corrupted with some tweets such as its only showing a single character such as (") or an emoji character. In example if the tweet says:
RT #jakemillermusic: Everyone upload your pics that you took today during the ustream and caption it "follow #jakemillermusic #jakemiller"
when shown with NSLog it prints :
2013-04-03 00:34:30.476 ParsingXMLTutorial[3308:c07] RT #jakemillermusic: Everyone upload your pics that you took today during the ustream and caption it
2013-04-03 00:34:30.476 ParsingXMLTutorial[3308:c07] "
2013-04-03 00:34:30.477 ParsingXMLTutorial[3308:c07] follow #jakemillermusic #jakemiller
2013-04-03 00:34:30.478 ParsingXMLTutorial[3308:c07] "
Here's the URL I am using to fetch the XML format:
http://api.twitter.com/1/statuses/user_timeline/LexxiSaal.xml?include_entities=true&include_rts=true&screen_name=twitterapi&trim_user=false&contributor_details=true&count=50
HERES THE PARSING CODE:
-(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
{
//string = [string stringByReplacingOccurrencesOfString:#" " withString:#""]; // space
string = [string stringByReplacingOccurrencesOfString:#"\n" withString:#""]; // newline
string = [string stringByReplacingOccurrencesOfString:#"\t" withString:#""];
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:#"status"])
{
currentTweet = [Tweet alloc];
isStatus = YES;
}
if ([elementname isEqualToString:#"user"])
{
isStatus = NO;
}
}
- (void) parser:(NSXMLParser *)parser didEndElement:(NSString *)elementname namespaceURI: (NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if (isStatus)
{
if ([elementname isEqualToString:#"created_at"])
{
currentTweet.dateCreated = currentNodeContent;
}
if ([elementname isEqualToString:#"text"])
{
currentTweet.content = currentNodeContent;
}
}
if ([elementname isEqualToString:#"status"])
{
[self.tweets addObject:currentTweet];
currentTweet = nil;
currentNodeContent = nil;
}
}
#end
I would suggest few changes as below
- (void) parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
NSString *value=[string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet];
if(currentNodeContent == nil){
currentNodeContent = [[NSMutableString alloc] initWithString:value];
}else
[currentNodeContent appendString:value];
}
and in didEnd
- (void) parser:(NSXMLParser *)parser didEndElement:(NSString *)elementname namespaceURI: (NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if (isStatus)
{
if ([elementname isEqualToString:#"created_at"])
{
currentTweet.dateCreated = currentNodeContent;
}
if ([elementname isEqualToString:#"text"])
{
currentTweet.content = currentNodeContent;
}
}
if ([elementname isEqualToString:#"status"])
{
[self.tweets addObject:currentTweet];
currentTweet = nil;
//currentNodeContent = nil; REMOVED
}
currentNodeContent = nil; // PUT OUTSIDE
}
The thing is you have to append string in method foundCharacters because the parser doesn't return all the string in between the tags at once..
And at last you should make the currentNodeContent nil, in the didEnd method globally because you are using it for other texts too.
Hope above helps..
Related
I am new to iOS development. I want to parse my xml web-service array. My xml response is like,
<BookList>
<Book>
<BookID>int</BookID>
<BookName>string</BookName>
<Pages>string</Pages>
<Price>string</Price>
</Book>
<Book>
<BookID>int</BookID>
<BookName>string</BookName>
<Pages>string</Pages>
<Price>string</Price>
</Book>
</BookList>
Here is the code i am using to parse the response,
-(void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSString *theXML = [[NSString alloc] initWithBytes:
[self.webResponseData mutableBytes] length:[self.webResponseData length] encoding:NSUTF8StringEncoding];
//now parsing the xml
NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithData: self.webResponseData];
xmlParser.delegate = self;
// Run the parser
#try{
BOOL parsingResult = [xmlParser parse];
}
#catch (NSException* exception)
{
UIAlertView* alert = [[UIAlertView alloc]initWithTitle:#"Server Error" message:[exception reason] delegate:self cancelButtonTitle:#"OK" otherButtonTitles: nil];
[alert show];
return;
}
}
//Implement the NSXmlParserDelegate methods
-(void) parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:
(NSString *)qName attributes:(NSDictionary *)attributeDict
{
currentElement = elementName;
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
// NSLog(#"String : %#", string);
if ([currentElement isEqualToString:#"BookID"]) {
NSLog(#"BookID : %#", string);
}else if ([currentElement isEqualToString:#"BookName"]) {
NSLog(#"BookName : %#", string);
}else if ([currentElement isEqualToString:#"Pages"]) {
NSLog(#"Pages : %#", string);
}else if ([currentElement isEqualToString:#"Price"]) {
NSLog(#"Price : %#", string);
}
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
// NSLog(#"Current Element: %# ",currentElement);
}
Using this code I can view the results, But i can get the number of books.
You can add this in to .h file
NSMutableDictionary *dictBook;
NSMutableArray *arrBook;
NSMutableString *elementValue;
Now use the below code to get the total book counts.
//Implement the NSXmlParserDelegate methods
-(void) parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:
(NSString *)qName attributes:(NSDictionary *)attributeDict
{
currentElement = elementName;
if ([currentElement isEqualToString:#"BookList"]) {
arrBook = [[NSMutableArray alloc] init];
}
else if ([currentElement isEqualToString:#"Book"]) {
dictBook = [[NSMutableDictionary alloc] init];
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
if(!elementValue)
elementValue = [[NSMutableString alloc] initWithString:string];
else
elementValue = string; //[elementValue appendString:string];
NSLog(#"elementValue : %#",elementValue);
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
// NSLog(#"Current Element: %# ",currentElement);
if ([elementName isEqualToString:#"BookID"] ||
[elementName isEqualToString:#"BookName"] ||
[elementName isEqualToString:#"Pages"] ||
[elementName isEqualToString:#"Price"])
{
[dictBook setObject:elementValue forKey:elementName];
}
else if ([elementName isEqualToString:#"Book"])
{
[arrBook addObject:dictBook];
}
// [elementValue setString:#""];
}
- (void)parserDidEndDocument:(NSXMLParser *)parser {
NSLog(#"Arr Book Count : %lu", (unsigned long)arrBook.count);
}
Hope this will help you.
I have an XML file somewhere on the web with a couple of profiles inside it and I want the number of profiles to be displayed in a textfield.
I have a textfield called: numberOfProfiles.. so what should I do in viewDidLoad?
numberOfProfiles.Text = ???
The XML file is being parsed like this:
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:#"firstname"])
{
currentProfile = [ViewController alloc];
isStatus = YES;
}
if([elementName isEqualToString:#"lastname"])
{
currentProfile = [ViewController alloc];
isStatus = YES;
}
if([elementName isEqualToString:#"email"])
{
currentProfile = [ViewController alloc];
isStatus = YES;
}
if([elementName isEqualToString:#"address"])
{
currentProfile = [ViewController alloc];
isStatus = YES;
}
}
-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if([elementName isEqualToString:#"firstname"])
{
currentProfile->firstName = currentNodeContent;
NSLog(#"%#",currentProfile->firstName);
[profile addObject:currentProfile];
}
if([elementName isEqualToString:#"lastname"])
{
currentProfile->lastName = currentNodeContent;
NSLog(#"%#",currentProfile->lastName);
[profile addObject:currentProfile];
}
if([elementName isEqualToString:#"email"])
{
currentProfile->eMail = currentNodeContent;
NSLog(#"%#",currentProfile->eMail);
[profile addObject:currentProfile];
}
if([elementName isEqualToString:#"address"])
{
currentProfile->address = currentNodeContent;
NSLog(#"%#",currentProfile->address);
[profile addObject:currentProfile];
}
if([elementName isEqualToString:#"profiles"])
{
[self->profile addObject:currentProfile];
currentProfile = nil;
currentNodeContent = nil;
setText:currentProfile->lastName;
}
}
- (void)viewDidLoad
{
[super viewDidLoad];
xmlParser = [[ViewController alloc] loadXMLByURL:#"http://dierenpensionlindehof.nl/profiles.xml"];
}
Thanks in advance!
for just count of element you can have an instance variable like of int type numberOfProfilesCount and you can increment this in
-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
numberOfProfilesCount++;
}
and in
- (void)parserDidEndDocument:(NSXMLParser *)parser {
numberOfProfiles.Text = [NSString stringWithFormate:#"%d", numberOfProfilesCount];
}
to show your element count
Assuming profile is a global variable, use [profile count] to get the number of profiles.
The try: [numberOfProfiles setText:[[profile count] stringValue]
I am trying to parse xml response and want data in NSDictionary.how can I get data in dictionary instead of NSMutableArray. Please help me ,getting response like :
<NewDataSet>
<Table>
<ID>105</ID>
<pk3>Apr 05, 2013</pk3>
<YEAR>2013</YEAR>
<TIME>09:10:46 PM</TIME>
</Table>
</NewDataSet>
Thanks in advance.
You can try with this..
.h /////////////////
#interface LoginWithTauky:UIViewController<NSXMLParserDelegate,NSURLConnectionDelegate>
{
NSXMLParser *xmlParser;
NSMutableString *soapResults;
BOOL xmlResults;
}
.m //////////////
-(void)Viewdidload
{
xmlParser = [[NSXMLParser alloc] initWithData:XMLdata];
[xmlParser setDelegate: self];
[xmlParser setShouldResolveExternalEntities: YES];
[xmlParser parse];
}
-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *) namespaceURI qualifiedName:(NSString *)qName
attributes: (NSDictionary *)attributeDict
{
NSLog(#"fsdfsd");
if( [elementName isEqualToString:#"Table"]||[elementName isEqualToString:#"ID"]||[elementName isEqualToString:#"pk3"]||[elementName isEqualToString:#"YEAR"]||[elementName isEqualToString:#"TIME"])
{
if(!soapResults)
{
soapResults = [[NSMutableString alloc] init];
}
xmlResults = YES;
}
}
-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
if( xmlResults )
{
[soapResults appendString: string];
NSLog(#"soap result %#",soapResults);
}
}
-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if( [elementName isEqualToString:#"Table"])
{
xmlResults = FALSE;
[user_idArray addObject:soapResults];
soapResults = nil;
}
if( [elementName isEqualToString:#"ID"])
{
xmlResults = FALSE;
[IDArray addObject:soapResults];
soapResults = nil;
}
if( [elementName isEqualToString:#"pk3"])
{
xmlResults = FALSE;
[IDArray addObject:soapResults];
soapResults = nil;
}
if( [elementName isEqualToString:#"YEAR"])
{
xmlResults = FALSE;
[IDArray addObject:soapResults];
soapResults = nil;
}
if( [elementName isEqualToString:#"TIME"])
{
xmlResults = FALSE;
[IDArray addObject:soapResults];
soapResults = nil;
}
}
This works fine , i have tested it. Check it out
-(IBAction)parseTheXml:(id)sender
{
NSString * mystr =[[NSString alloc]initWithFormat:#"<NewDataSet>"
"<Table>"
"<ID>105</ID>"
"<pk3>Apr 05, 2013</pk3>"
"<YEAR>2013</YEAR>"
"<TIME>09:10:46 PM</TIME>"
"</Table>"
"</NewDataSet>" ];
NSData * mydata =[mystr dataUsingEncoding:NSUTF8StringEncoding];
if(!parser)
parser =[[NSXMLParser alloc]initWithData:mydata];
[parser setDelegate:self];
[parser setShouldResolveExternalEntities:YES];
BOOL success= [parser parse];
if(success)
{
NSLog(#"SUCCESS");
}
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
NSLog(#"the tag is %#",elementName);
if(!([elementName isEqualToString:#"Table"] ||[elementName isEqualToString:#"NewDataSet"]))
{
if(!dataDict)
dataDict =[[NSMutableDictionary alloc]init];
datastring =[[NSMutableString alloc]init];
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
datastring = [NSMutableString stringWithFormat:#"%#",string];
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if(!([elementName isEqualToString:#"Table"] ||[elementName isEqualToString:#"NewDataSet"]))
{
if([elementName isEqualToString:#"VideoThumbnail"])
NSLog(#"the string is : %#",datastring);
[dataDict setObject:datastring forKey:elementName];
}
}
it will give you dictionary like this :
2013-12-05 16:24:05.959 parsingXML[3305:c07] the string we get is {
ID = 105;
TIME = "09:10:46 PM";
YEAR = 2013;
pk3 = "Apr 05, 2013";
}
I'm trying to parse this xml file. The problem I'm having is that I'd like to use the
-(void)parser:(NSXMLParser*)parser didStartElement ...
to drill down into several levels of this xml file.
This is what I have so far:
#pragma didStartElement (from the parser protocol)
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
// Choose the tag
if ([elementName isEqualToString:#"item"]) {
NSString *firstName = [attributeDict valueForKey:#"firstname"];
NSString *lastName = [attributeDict valueForKey:#"lastname"];
NSString *birthDay = [attributeDict valueForKey:#"birthday"];
Politician *politician = [[Politician alloc] initWithName:firstName lName:lastName bDay:birthDay];
if (politician != nil) {
[people addObject:politician];
}
}
}
The problem is that this code does not drill down. Is there a way to selectively start the parsing from a specific tag (say: person) and check for the keys of that tag or to rewrite the "elementName's" value so I can use multipe if statements? What's the right way of doing this? Thanks much.
You couldnt get the firstname,lastname,etc in your attributeDict. Attribute dictionary holds values like in the below format
<count n="1">
In the above example attributeDict holds the value for n
In order to parse the given xml, you can use the below code.
Declare the objects
Politician *politician;
NSString *curElement;
NSMutableArray *politicians;
BOOL isCongressNumbers;
Initialize the politicians in viewDidLoad
politicians = [[NSMutableArray alloc]init];
Add the delegate methods
#pragma mark - NSXMLParser Delegate
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
if ([elementName isEqualToString:#"item"]) {
politician = [[Politician alloc]init];
} else if ([elementName isEqualToString:#"congress_numbers"]) {
isCongressNumbers = YES;
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
curElement = string;
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if ([elementName isEqualToString:#"item"] && !isCongressNumbers) {
[politicians addObject:politician];
} else if ([elementName isEqualToString:#"firstname"]) {
politician.name = curElement;
} else if ([elementName isEqualToString:#"lastname"]) {
politician.lName = curElement;
} else if ([elementName isEqualToString:#"birthday"]) {
politician.bDay = curElement;
} else if ([elementName isEqualToString:#"congress_numbers"]) {
isCongressNumbers = NO;
}
}
You can
1) new a Politician in the didStartElement method and assign the element name in one instance variable.
2) assign the properties of Politician in the foundCharacters according to the instance variable you assigned in 1).
3) add the Politician to the people in the didEndElement.
Hope this is helpful.
The sample code is as follows:
declare some instance variables:
Politican *politican;
NSString *currentElement;
NSMutableArray *politicians;
init the arrays:
politicians = [[NSMutableArray alloc] init];
implement the delegate methods.
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
currentElement = elementName;
if ([elementName isEqualToString:#"item"]) {
politician = [[Politician alloc] init];
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
if([string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]].length<1)
return; // avoid some white space
if ([currentElement isEqualToString:#"firstname"]) {
politician.firstname = string;
} else if ([currentElement isEqualToString:#"lastname"]) {
politician.lastname = string;
} else if ([currentElement isEqualToString:#"birthday"]) {
politician.birthday = string;
}
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if ([elementName isEqualToString:#"item"]) {
[politicians addObject:politician];
}
}
Anyway this is just a sample, you'd better write all the if else statements according to your xml.
In your xml file, there are several tags named the same item. you can try to make one more instance variable to store the previous tag to make the difference and do the assignments.
In.h file
#property (strong, nonatomic) NSXMLParser *xmlParser;
#property (nonatomic, retain) NSMutableDictionary *lResponseDict;
#property (nonatomic, weak) NSString *currentElement;
NSString* UDID = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
NSLog(#"UDID:: %#", UDID);
NSString *urlString = [NSString stringWithFormat:#"urlHere"];
NSString *jsonString = [NSString stringWithFormat:LOGIN,self.cUsernameTxtFld.text,self.cPasswordTxtFld.text,UDID];
NSData *myJSONData =[jsonString dataUsingEncoding:NSUTF8StringEncoding];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:[NSURL URLWithString:urlString]];
[request setHTTPMethod:#"POST"];
[request setValue:#"text/html" forHTTPHeaderField:#"Accept"];
NSMutableData *body = [NSMutableData data];
[body appendData:[NSData dataWithData:myJSONData]];
[request setHTTPBody:body];
NSError *error;
NSURLResponse *response;
NSData *urlData=[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSString *str = [[NSString alloc]initWithData:urlData encoding:NSUTF8StringEncoding];
if(str.length > 0)
{
self.xmlParser = [[NSXMLParser alloc] initWithData:urlData];
self.xmlParser.delegate = self;
// Start parsing.
[self.xmlParser parse];
}
#pragma mark - NSXML Parsar Delegate Methods.
- (void)parserDidStartDocument:(NSXMLParser *)parser
{
// NSLog(#"Parsing Initiated.");
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
self.currentElement = elementName;
if([elementName isEqualToString:#"data"])
{
// NSLog(#"%#",elementName);
self.lResponseDict = [[NSMutableDictionary alloc]init];
}
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if([elementName isEqualToString:#"data"])
{
// NSLog(#"%#",elementName);
NSLog(#"Final Dict: %#", _lResponseDict);
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
//NSLog(#"%#", string);
[_lResponseDict setObject:string forKey:_currentElement];
}
-(void)parserDidEndDocument:(NSXMLParser *)parser
{
}
Hope you are getting the URL data ... so with SMXMLParser, it is easier to parse using one by one node ...
In the below mentioned example, I am using AFNetworking with SMXMLParser . Hope you get the idea ....
NSString *soapRequest=[NSString stringWithFormat:#"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
"<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n"
"<soap:Body>\n"
// Your parameters here …. //
"</soap:Body>\n"
"</soap:Envelope>\n"];
NSString *urlStr = #"Your URL";
NSURL *urlNew = [NSURL URLWithString:urlStr];
NSMutableURLRequest *request=[appDel generateRequestWithUrl:urlNew request:soapRequest];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSError *error=nil;
dictCarList = [[NSMutableDictionary alloc]init];
SMXMLDocument *document=[[SMXMLDocument alloc]initWithData:operation.responseData error:&error];
if (error) {
NSLog(#"Error while parsing the document: %#", error);
[indicatorView removeFromSuperview];
return;
}
count++;
SMXMLElement *element1 = [document.root childNamed:#"objects"];
SMXMLElement *element2 = [element1 childNamed:#"The Tag you want to get"];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error:%#",error);
}];
I'm trying to obtain the url contained in media:content tag of the Yahoo RSS feed. The code for didStartElement(), foundCharacters() and didEndElement() is given below:
- (void)parser:(NSXMLParser *)parser
didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName
attributes:(NSDictionary *)attributeDict {
if ([elementName isEqualToString:kChannelElementName]) {
Channel = [[channel alloc] init];
dict=[[NSMutableDictionary alloc] init];
[Channel setItemCollectionArray:[[NSMutableArray alloc] init]];
return ;
}
if ([elementName isEqualToString:kItemElementName]) {
itemCollection=[[ItemDataCollection alloc] init];
return ;
}
if ([elementName isEqualToString:kTitleElementName]) {
return ;
}
if([elementName isEqualToString:kItemDescription]){
return ;
}
if ([elementName isEqualToString:kItemImage]) {
NSString *urlString = attributeDict[#"url"];
if(urlString){
[dict setObject:urlString forKey:#"img"];
}
return ;
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
if (currentElementData == nil) {
self.currentElementData = [[NSMutableString alloc] init];
}
[currentElementData appendString:string];
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName {
if ([elementName isEqualToString:kChannelElementName]) {
[channelCollection addObject:Channel];
NSLog(#"channel are***********%#",channelCollection);
for(ItemDataCollection *mydata in Channel.itemCollectionArray){
NSLog(#"___%# <><><><><> desc \n %# <><><><><><> img \n %#",mydata.title,mydata.itemDescription,mydata.titleImage);
}
Channel =nil;
}
else if ([elementName isEqualToString:kItemElementName]) {
[[Channel itemCollectionArray] addObject:itemCollection];
itemCollection=nil;
}
else if ([elementName isEqualToString:kTitleElementName]) {
if(itemCollection==nil){
Channel.title=currentElementData;
}
else{
itemCollection.title=currentElementData;
}
}
else if ([elementName isEqualToString:kPubDate]) {
Channel.pubDate=currentElementData;
}
else if ([elementName isEqualToString: kItemDescription]) {
if(itemCollection!=nil){
itemCollection.itemDescription=currentElementData;
}
}
else if([elementName isEqualToString:#"media:content"]){
if(itemCollection!=nil){
itemCollection.titleImage = currentElementData;
}
}
// [currentElementData release];
self.currentElementData = nil;
}
I'm printing the parsed data as log. The image is showing as null. Everything else eg;title and description is getting obtained properly. How can I fix it? Probably something needs to be done in the didEndElement method. But I don't know what. I've been racking my brains over this since yesterday. Please help!!
I made some changes in didStartElement():
if ([elementName isEqualToString:kItemImage]) {
NSString *urlString = attributeDict[#"url"];
if(urlString){
[dict setObject:urlString forKey:#"img"];
NSLog(#"%#",urlString);
mString = [NSString stringWithFormat:urlString];
and some change in didEndElement():
else if([currentElementData rangeOfString:#"media:content"].location){
if(itemCollection!=nil){
// [currentElementData appendString:dict];
itemCollection.titleImage = mString;
}
}
mString has been declared as a mutable string. Images are getting parsed now. Their urls are getting displayed in the log. The problem is that now, the last image is repeated twice.. It is probably because the last feed does not have an image, so it is using the previous one. How to fix that? I mean, there can be multiple feeds without images. in that case, it should actually display null rather than the url of the previous image.
I don`t know well about Yahoo rss feed but i hope it will help you.....
Just tryout this....
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
currentElement = [elementName copy];
if ([elementName isEqualToString:#"item"]) {
item = [[NSMutableDictionary alloc] init];
currentTitle = [[NSMutableString alloc] init];
currentDate = [[NSMutableString alloc] init];
currentSummary = [[NSMutableString alloc] init];
currentLink = [[NSMutableString alloc] init];
currentImage = [[NSMutableString alloc] init];
}
else if([elementName isEqualToString:#"media:content"]) {
currentImage = [attributeDict objectForKey:#"img src"];
NSLog(#"Url:%#", currentImage);
}
}
}