NSXML didStartElement method not being called - ios

Iv'e set my h as the delegate and I'm calling the "setDelegate:self" method on my xml parser.
here is my code.
-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
elementName = element;
if ([elementName isEqualToString:#"offer"]) {
offersDictionary = [[NSMutableDictionary alloc] init];
offerTitle = [[NSMutableString alloc] init];
offerDay = [[NSMutableString alloc] init];
offerDet = [[NSMutableString alloc] init];
NSLog(#"PARSER didStartElement method!");
}
}
-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
if ([element isEqualToString:#"offerTitle"]) {
[offerTitle appendString:string];
}
if ([element isEqualToString:#"day"]) {
[offerDay appendString:string];
}
if ([element isEqualToString:#"offerDetail"]) {
[offerDet appendString:string];
}
}
-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
if ([elementName isEqualToString:#"offer"]) {
[offersDictionary setObject:offerTitle forKey:#"offerTitle"]; NSLog(#"offerTitle:%#",offerTitle);
[offersDictionary setObject:offerDet forKey:#"offerDetail"]; NSLog(#"offerDet:%#",offerDet);
[offersDictionary setObject:offerDay forKey:#"day"]; NSLog(#"OfferDay:%#",offerDay);
NSLog(#"DidEndELEMENT");
//[offersArray addObject:[offersDictionary copy]];
}
}
I've set "NSlog" in my didStartElement and in my didEndElement methods, but I only get output from the didEndElement.
I'm calling the "parse" method of the NSXML from the viewDidLoad method.
here is my viewDidLoad method.
- (void)viewDidLoad
{
[super viewDidLoad];
//alloc and init the array
offersArray = [[NSMutableArray alloc] init];
//create NSUrl with the xml file
NSURL *xmlUrl = [NSURL URLWithString:#"http://mydomain.org/dir/dir/file.xml"];
//alloc and init the xml parser with the data of the file
xmlParser = [[NSXMLParser alloc]initWithContentsOfURL:xmlUrl];
//set some methods on the xml parser
[xmlParser setDelegate:self];
[xmlParser setShouldProcessNamespaces:NO];
[xmlParser setShouldReportNamespacePrefixes:NO];
[xmlParser setShouldResolveExternalEntities:NO];
//create a 'success gate' of the 'parse' method
BOOL xmlParseSuccess = [xmlParser parse];
if (xmlParseSuccess) {
NSLog(#"Successed Parsing! array Has %lu elements.", (unsigned long)offersArray.count);
} else if (!xmlParseSuccess) {
NSLog(#"Error Parsing!");
}
// Do any additional setup after loading the view.
}
Why is the didStartElement method not being called?

Here is your issue:
-(void)parser:(NSXMLParser *)parser
didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName
attributes:(NSDictionary *)attributeDict {
/*
Your setting elementName to element. So whatever the
value of 'element' is, it will compare to #"offer".
It seems that the value of 'element' is not equal
to #"offer". You should not be Comment this line out
and it should work fine.
*/
elementName = element;
if ([elementName isEqualToString:#"offer"]) {
offersDictionary = [[NSMutableDictionary alloc] init];
offerTitle = [[NSMutableString alloc] init];
offerDay = [[NSMutableString alloc] init];
offerDet = [[NSMutableString alloc] init];
NSLog(#"PARSER didStartElement method!");
}
}

Related

Display number of XML elements in a textfield

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]

Can't find the thumbnail element in RSS feed

I'm doing a test where I'm building a news feed iOS app, using rss feeds like this one: http://www.20minutos.es/iphoneapp/feeds/home/
I'm almost done, but I can't find the link to the thumbnail. I'm doing the parsing like this and I can find some enclosure, enclosure2x, thumbnail, thumbnail2x, but they're all empty strings:
- (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];
image = [[NSMutableString alloc] init];
image2x = [[NSMutableString alloc] init];
comments = [[NSMutableString alloc] init];
}
}
- (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:image forKey:#"image"];
[item setObject:image2x forKey:#"image2x"];
[item setObject:comments forKey:#"comments"];
[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:#"veinteminutos:numComments"]) {
[comments appendString:[string stringByReplacingOccurrencesOfString:#" " withString:#""]];
}
//NSLog(#"string: %# \nelement: %# \n\n\n", string, element);
}
It's my first time parsing rss feeds, so I don't really know what to look for in there.
Thanks
You should parse out the media:thumbnail and media:thumbnail2x nodes in the parser:didStartElement:namespaceURI:qualifiedName:attributes: delegate method and extract the thumbnail URLs from the attributeDict dictionary:
- (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];
image = [[NSMutableString alloc] init];
image2x = [[NSMutableString alloc] init];
comments = [[NSMutableString alloc] init];
} else if ([element isEqualToString:#"media:thumbnail"]) {
image = [attributeDict objectForKey:#"url"];
} else if ([element isEqualToString:#"media:thumbnail2x"]) {
image2x = [attributeDict objectForKey:#"url"];
}
}
You can do the same for the enclosures, should you need them.

How can I set key-value pair in NSMutableDictionary as XML attribute-element values using NSXMLParser

I am using NSXMLParser to parse my XML with the following structure:
<characters>
<character>
<literal>本</literal>
<codepoint>
<cp_value cp_type="ucs">672c</cp_value>
<cp_value cp_type="jis208">43-60</cp_value>
</codepoint>
</character>
</characters>
I want to use the cp_value element's attribute_value as a key and the element value (e.g. 672c) as the value and place this key-value pair in my NSMutableDictionary *_codepoint. After parsing, I want the result (in the console) to look like this:
_codepoint: {
"ucs"=672c;
"jis208"=43-60;
}
As I have implemented the parser (code follows), I am getting this back in the console:
2013-01-22 22:12:46.199 MyApp[13391:c07] _codepoint: {
ucs = "\n \n ";
}
2013-01-22 22:12:46.201 MyApp[13391:c07] _codepoint: {
jis208 = "\n \n 672c\n ";
}
First - the values and keys are out-of-sync and second, the value for the jis208 element is not getting read-in. Second, I'm not sure what these \n and whitespaces are. Can anybody please give some advice?
The code I have written is:
- (void)parser:(NSXMLParser *)parser
didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName
attributes:(NSDictionary *)attributeDict
{
if([elementName isEqualToString:#"characters"]) {
appDelegate.characters = [[NSMutableArray alloc] init];
} else if ([elementName isEqualToString:#"character"]) {
aCharacter = [[Character alloc] init];
} else if ([elementName isEqualToString:#"cp_value"]) {
if (!_codepoint) _codepoint = [[NSMutableDictionary alloc] init];
[_codepoint setValue:currentElementValue forKey:[attributeDict valueForKey:[[attributeDict allKeys] lastObject]]];
NSLog(#"_codepoint: %#", _codepoint);
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
if (!currentElementValue) {
currentElementValue = [[NSMutableString alloc] initWithString:string];
} else {
[currentElementValue appendString:string];
}
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if ([elementName isEqualToString:#"characters"]
// cp_values will be copied from a local NSMutableDictionary *_codepoint
|| [elementName isEqualToString:#"codepoint"]
) return;
if ([elementName isEqualToString:#"character"]) {
[appDelegate.characters addObject:aCharacter];
[aCharacter release];
} else if ([elementName isEqualToString:#"cp_value"]){
[aCharacter.codepoint addObject:_codepoint];
}
}
Thank you very much for looking.
problem is that you are adding currentElementValue to _codepoint before reading actual value into currentElementValue i.e you are adding it in when cp_value is started. you should add currentElementValue to _codepoint in didEndElement: delegate method.Then you'll get expected result.Modify your code like this:
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
if([elementName isEqualToString:#"characters"]) {
appDelegate.characters = [[NSMutableArray alloc] init];
} else if ([elementName isEqualToString:#"character"]) {
aCharacter = [[Character alloc] init];
} else if ([elementName isEqualToString:#"cp_value"]) {
if (!_codepoint) _codepoint = [[NSMutableDictionary alloc] init];
currentAttributeKey = [[NSMutableString alloc]initWithString:[attributeDict valueForKey:[[attributeDict allKeys] lastObject]]];
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
if (!currentElementValue) {
currentElementValue = [[NSMutableString alloc] initWithString:string];
} else {
[currentElementValue appendString:string];
}
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if ([elementName isEqualToString:#"characters"] || [elementName isEqualToString:#"codepoint"])
return;
if ([elementName isEqualToString:#"character"]) {
[appDelegate.characters addObject:aCharacter];
[aCharacter release];
} else if ([elementName isEqualToString:#"cp_value"]){
[_codepoint setValue:[[currentElementValue componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] componentsJoinedByString:#""] forKey:currentAttributeKey];
currentElementValue = [[NSMutableString alloc]init];
NSLog(#"_codepoint: %#", _codepoint);
[aCharacter.codepoint addObject:_codepoint];
}
}
where currentAttributeKey is NSMutableString that will store the attributes.In your case ucs and jis208

Parsed xml file but the array is showing null

I have parsed the xml file.
The console is showing the parsed elements correctly but the array is showing null.
- (ParserClass *) 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:#"note"]) {
//Initialize the array.
appDelegate.testArray = [[NSMutableArray alloc] init];
}
else if([elementName isEqualToString:#"to"]) {
aTest = [[Test alloc] init];
}
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;
if([elementName isEqualToString:#"note"]) {
[appDelegate.testArray addObject:aTest];
//[aBook release];
aTest = nil;
}
else
[aTest setValue:currentElementValue forKey:elementName];
//[currentElementValue release];
currentElementValue = nil;
}
#end
Try to change your initialization to:
- (ParserClass *) initXMLParser {
self=[super init];
if(self !=nil){
appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
// init array of user objects here
appDelegate.testArray = [[NSMutableArray alloc] init];
}
return self;
}
And,if your xml is:
<books>
<note>
<something>cccc</something>
</note>
<note>
<something>cccc</something>
</note>
</books>
So you need change:
-(void)parser: (NSXMLParser *)parser didStartElement:(NSString *) elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName
attributes:(NSDictionary *)attributeDict {
if([elementName isEqualToString:#"note"]) {
aTest = [[Test alloc] init];
//if you have attributes, you can extract them here:
// user.att = [[attributeDict objectForKey:#"<att name>"] ...];
}
NSLog(#"Processing Element: %#", elementName);
}
And to get your array you must do something like this:
//Data store your xml
NSXMLParser *nsXmlParser = [[NSXMLParser alloc] initWithData:Data];
ParserClass *parser = [[ParserClass alloc] initXMLParser];
//delegate your parser
[nsXmlParser setDelegate:parser];
//it's doing parsing
BOOL success = [nsXmlParser parse];
if (success)
{
NSMutableArray *someArray = [parser appDelegate.testArray ];
NSLog(#"%#",someArray );
} else
{
NSLog(#"Error parsing document!");
}
try it , it working for me...

xml parsing having multiple opening tags

I m getting response like this
<NewDataSet>
<Map>
<URL>
https://maps.google.co.in/maps?q=ABIL+House,+Ganeshkhind+Road,+Yashwant+nagar,+Pune,+Maharashtra&hl=en&sll=18.539118,73.834095&sspn=0.011169,0.021136&oq=ABIL+House&t=h&hnear=ABIL+House,+2,+Ganeshkhind+Rd,+Yashwant+nagar,+Pune,+Maharashtra+411007&z=16
</URL>
</Map>
</NewDataSet>
I have to parse url value to show in web view. How to parse xml file having two opening tags, this is my code:
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
if ([elementName isEqualToString:#"Result"]) {
item = [[NSMutableDictionary alloc] init];
currentUser =[[NSMutableString alloc] init];
}
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if ([elementName isEqualToString:#"Result"]) {
[item setObject:currentUser forKey:#"Result"];
// [item setObject:currentPassword forKey:#"Name"];
[users addObject:[item copy]];
}
}
- (void)parser:(NSXMLParser )parser foundCharacters:(NSString *)string
{
if ([currentElement isEqualToString:#"Result"]) {
[currentUser appendString:string];
}
/* if ([currentElement isEqualToString:#"Name"])
{
[currentPassword appendString:string];
}
*/
}
- (void)viewDidLoad
{
users = [[NSMutableArray alloc] init];
NSURL *xmlURL = [NSURL URLWithString:#"http://abilcms.com.sv2.premiumwebserver.com/WebServiceStatus.aspx?UserID=demo#abil.com"];
xmlParser = [[NSXMLParser alloc] initWithContentsOfURL:xmlURL];
[xmlParser setDelegate:self];
[xmlParser parse];
NSLog(#"name=%#",currentUser);
statuslabel.text= currentUser;
}
Here is a tutorial on xml parsing in ios that shows how it is done. http://theappcodeblog.com/2011/05/09/parsing-xml-in-an-iphone-app-tutorial
Here is another tutorial on accessing multi level XML documents
But as far as I can see you should just replace "Result" with "URL" if this is the only URL tag in your XML, as fa as I understand NSXMLParser will handle the levels for you in this case. Of course if there is more data in this XML that you need to access you should build it like the example in the second link.

Resources