i m not able to get processing values beyond "iid". giving exception:
[ setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key iid.'
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName
attributes:(NSDictionary *)attributeDict {
if([elementName isEqualToString:#"NewDataSet"])
{
appDelegate.books = [[NSMutableArray alloc] init];
}
else if([elementName isEqualToString:#"Table"])
{
if([elementName isEqualToString:#"id"])
{
{
aBook = [[Book 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:#"Tablesreturn"])
//return;
if([elementName isEqualToString:#"Table"])
{
[appDelegate.books addObject:aBook];
[aBook release];
aBook = nil;
}
else
[aBook setValue:currentElementValue forKey:elementName];
[currentElementValue release];
currentElementValue = nil;
}
It's not finding the iid value. It's case sensitive, so check if you're using the wrong case in your label name.
If you're not looking for too many values maybe you can just do a manual if then else for all the xml nodes you're interested in.
something like -
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
if([elementName isEqualToString:#"Table"])
{
[appDelegate.books addObject:aBook];
[aBook release];
aBook = nil;
}
else if([elementName isEqualToString:#"xyz"])
{
[aBook setValue:currentElementValue forKey:#"xyz"];
}
// and so on, for the rest of the nodes.
[currentElementValue release];
currentElementValue = nil;
}
in ur Book class verify all tags or fields specified in .h file.......reply me
like Table, Tablesreturn.......all of them.
and synthesize all of them
Related
This question already has answers here:
Custom class NSObject not key value coding compliant [duplicate]
(4 answers)
Closed 9 years ago.
My app is crashing, any thoughts please? I am parsing the xml in my code, here is the code.
if i removed this line it works fine
[listItem setValue:currentElementValue forKey:elementName];
Thanks
-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{
if ([elementName isEqualToString:#"channel"]) {
NSLog(#"found channel");
app.listArray = [[NSMutableArray alloc]init];
}
else if([elementName isEqualToString:#"item"]){
listItem = [[NewsList alloc] init];
listItem.title = [attributeDict objectForKey:#"title"];
listItem.description = [attributeDict objectForKey:#"description"];
}
}
-(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:#"channel"]) {
return;
}
if ([elementName isEqualToString:#"item"]) {
[app.listArray addObject:listItem];
listItem = nil;
}
else{
NSLog(#"element name = %#", elementName);
[listItem setValue:currentElementValue forKey:elementName];
}
currentElementValue = nil;
}
Your object listItem is of class NewsList. Since you get the error when you use setValue:forKey:, this class NewsList either has no property with name elementName and instance variable elementName or _elementName, or the setter method setElementName: has not been implemented.
Please check that you have set up your property correctly, e.g. using #property and #synthesize.
I parse a xml file to get the content of two nodes "tagid" and "mac".
How can I store this content in two arrays, one for "tagid" and one for "mac"?
The "parser" works. Thank you in advance
-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
self.currentElement = elementName;
self.currentElement2 = elementName;
if ([self.currentElement isEqualToString:#"mac"]) {
self.currentTitle = [NSMutableString string];
}
if ([self.currentElement2 isEqualToString:#"tagid"]) {
self.currentTitle2 = [NSMutableString string];
}
}
-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
if ([self.currentElement isEqualToString:#"mac"]) {
NSLog(#"%#", self.currentTitle);
}
if ([self.currentElement2 isEqualToString:#"tagid"]) {
NSLog(#"%#", self.currentTitle2);
}
self.currentTitle = nil;
self.currentElement = nil;
self.currentTitle2 = nil;
self.currentElement2 = nil;
}
-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
if (!self.currentElement) return;
if ([self.currentElement isEqualToString:#"mac"]) {
self.currentTitle = string;
}
if (!self.currentElement2) return;
if ([self.currentElement2 isEqualToString:#"tagid"]) {
self.currentTitle2 = string;
}
}
- (IBAction)aktualisieren:(id)sender {
NSURL *xmlURL = [[NSURL alloc] initWithString:#"http://mysite/mycontent"];
parser = [[NSXMLParser alloc] initWithContentsOfURL:xmlURL];
[parser setDelegate:self];
[parser parse];
}
Thank you for your responses :)
create two arrays in parseStartDocument. one for mac-MacArray , one for tagid-tagArray.
in didEndElement method,check for element & add your self.currentTitle to that perticular your Array.
In .h declare two arrays tagArray and macArray.
In viewDidLoad alloc init both arrays.
-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
if ([self.currentElement isEqualToString:#"mac"]) {
[macArray addObject:self.currentTitle];
NSLog(#"%#", self.currentTitle);
}
if ([self.currentElement2 isEqualToString:#"tagid"]) {
[macArray addObject:self.currentTitle2];
NSLog(#"%#", self.currentTitle2);
}
self.currentTitle = nil;
self.currentElement = nil;
self.currentTitle2 = nil;
self.currentElement2 = nil;
}
You need two different arrays
-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
self.currentElement = elementName;
self.currentElement2 = elementName;
if ([self.currentElement isEqualToString:#"mac"]) {
self.currentTitle = [NSMutableString string];
NSMutableArray *macArray = [NSMutableArray alloc] init];
}
if ([self.currentElement2 isEqualToString:#"tagid"]) {
self.currentTitle2 = [NSMutableString string];
NSMutableArray *tagIdArray = [NSMutableArray alloc] init];
}
}
-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
if ([self.currentElement isEqualToString:#"mac"]) {
NSLog(#"%#", self.currentTitle);
[macArray addObject:self.currentTitle];
}
if ([self.currentElement2 isEqualToString:#"tagid"]) {
NSLog(#"%#", self.currentTitle2);
[tagIdArray addObject:self.currentTitle2];
}
self.currentTitle = nil;
self.currentElement = nil;
self.currentTitle2 = nil;
self.currentElement2 = nil;
}
Declare two mutable arrays:
NSMutableArray *macArray , *tagidArray;
macArray = [[NSMutableArray alloc]init];
tagidArray = [[NSMutableArray alloc]init];
-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
if ([self.currentElement isEqualToString:#"mac"]) {
[macArray addObject:self.currentTitle];
NSLog(#"%#", self.currentTitle);
}
if ([self.currentElement2 isEqualToString:#"tagid"]) {
[tagidArray addObject:self.currentTitle2];
NSLog(#"%#", self.currentTitle2);
}
}
-(void)parserDidEndDocument{
//Do something as parsing has been completed here and your values are in two arrays
}
Find detailed parsing example here
By the way, if either of these was a long string, might get separated into multiple calls to foundCharacters. Thus, foundCharacters should always append strings, not setting strings:
-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
if (!self.currentElement) return;
if ([self.currentElement isEqualToString:#"mac"]) {
[self.currentTitle appendString:string];
}
if (!self.currentElement2) return;
if ([self.currentElement2 isEqualToString:#"tagid"]) {
[self.currentTitle2 appendString:string];
}
}
Im trying to parse a xml feed in my app... The xml file is in this url
feeds.feedburner.com/blogspot/TUvAW?format=xml
The problem is that when I access the description segment it diplays different special symbols such as quotation marks. This is one of the descripton segments im trying to parse from my xml:
<description>Este es mi blog 3<img src="http://feeds.feedburner.com/~r/blogspot/TUvAW/~4/URCV9ModTR0" height="1" width="1"/></description>
Im parsing it with the NSXMLParser, these are the method I'm using in my:
XMLParser.m
- (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:#"item"])
{
currentFeed = [Feed alloc];
isStatus = YES;
}
if ([elementname isEqualToString:#"author"])
{
isStatus = NO;
}
}
- (void) parser:(NSXMLParser *)parser didEndElement:(NSString *)elementname namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if (isStatus)
{
if ([elementname isEqualToString:#"description"])
{
currentFeed.description = currentNodeContent;
NSLog(#"%#",currentNodeContent);
}
if ([elementname isEqualToString:#"title"])
{
currentFeed.content = currentNodeContent;
NSLog(#"%#",currentNodeContent);
}
if ([elementname isEqualToString:#"link"])
{
currentFeed.WVUrl = currentNodeContent;
NSLog(#"%#",currentNodeContent);
}
}
if ([elementname isEqualToString:#"item"])
{
[self.feeds addObject:currentFeed];
currentFeed = nil;
currentNodeContent = nil;
}
}
Im using those NSLogs to track the strings that Im getting from the parse but my description node content is always showing just this : >
The title and link nodes are displaying perfectly.
I want to get all that string from the description node to use it later but simply I can't, I dont know whats going wrong with this.
The problems have been outlined by Abhishek, Rob and me. But I think it's worth to summarize it and show the correct solution.
The main problem is that parser:foundCharacters: is called several times for the <description> tag, each call providing a piece of the description.
The solution is to concatenate the pieces:
XMLParser.h:
NSMutableString* currentNodeContent;
XMLParser.m:
- (void) parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
if (currentNodeContent == nil)
currentNodeContent = [[NSMutableString alloc] initWithCapacity: 20];
[currentNodeContent appendString: [string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]];
}
- (void) parser:(NSXMLParser *)parser didStartElement:(NSString *)elementname namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
if ([elementname isEqualToString:#"item"])
{
currentFeed = [Feed alloc];
isStatus = YES;
}
if ([elementname isEqualToString:#"author"])
{
isStatus = NO;
}
}
- (void) parser:(NSXMLParser *)parser didEndElement:(NSString *)elementname namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if (isStatus)
{
if ([elementname isEqualToString:#"description"])
{
currentTweet.description = currentNodeContent;
NSLog(#"%#",currentNodeContent);
}
if ([elementname isEqualToString:#"title"])
{
currentTweet.content = currentNodeContent;
NSLog(#"%#",currentNodeContent);
}
if ([elementname isEqualToString:#"link"])
{
currentFeed.WVUrl = currentNodeContent;
NSLog(#"%#",currentNodeContent);
}
}
if ([elementname isEqualToString:#"item"])
{
[self.feeds addObject:currentFeed];
currentFeed = nil;
[currentNodeContent release];
currentNodeContent = nil;
}
}
The problem in the Xml file is use of "&" Character.
Do one this just get the xml data in one string and then replace "&" with any unique string and then parse your xml.
While showing or use of xml data just check if the string you are getting contains the same unique string in it then replace that string with the "&".
I am parsing data using NSXMLParser.
I am able to get the parsed data. But when I add it to the NSMutableArray using addObject, the array is empty.
I am using the latest Xcode version.
Can someone please help me out.
The array I am working on is identificationTypes1
-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{
if ([elementName isEqualToString:#"Books"]) {
}
if ([elementName isEqualToString:#"Book"]) {
if ([elementName isEqualToString:#"title"]) {
self.identificationTypes1 =[[NSMutableArray alloc]init];
}
}
}
-(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:#"Books"]) {
NSLog(#"Count is %#",[identificationTypes1 count]);
return;
}
if ([elementName isEqualToString:#"Book"]) {
}
if ([elementName isEqualToString:#"title"]) {
NSLog(#"Curre value is %#",currentElementValue);
[self.identificationTypes1 addObject:currentElementValue];
}
currentElementValue = nil;
}
NSMutabeArray *myArray = [[NSMUtableArray alloc]init];
[myArray addObject:<XML Data>];
You cannot nest elements as you have in didStartElement. Parsers do not allow that.
Take out the title out on its own and retest. You need to make new variables that are accessed conditionally.
I've been trying for some time now to get xml parser working leak free and efficient but so far unsuccessful. I've removed additional fields as they are all the same.
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{
currentElement = [[elementName copy] autorelease];
if ([elementName isEqualToString:#"source"]) {
if (!currentID) {
overlays = [[NSMutableArray alloc] init];
currentID = [[NSMutableString alloc] init];
} else {
[currentID release];
currentID = nil;
currentID = [[NSMutableString alloc] init];
}
}
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
if ([elementName isEqualToString:#"source"]) {
overlay = [[NSMutableDictionary alloc] init];
[overlay setObject:currentID forKey:#"id"];
[overlays insertObject:overlay atIndex:[overlays count]];
[overlay release];
overlay = nil;
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
string = [string stringByReplacingOccurrencesOfString:#"\n" withString:#""];
string = [string stringByReplacingOccurrencesOfString:#"\t" withString:#""];
if ([currentElement isEqualToString:#"id"]) {
[self.currentID appendString:string];
}
}
- (void)parserDidEndDocument:(NSXMLParser *)parser {
[currentID release];
currentID = nil;
//[self addResources];
}
Any help would be appreciated.
If you have declared properties for your ivars I would recommend to use them. This makes memory management easier. This is how I would write your code:
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{
self.currentElement = elementName;
if ([elementName isEqualToString:#"source"]) {
if (!self.currentID) {
self.overlays = [NSMutableArray array];
self.currentID = [NSMutableString string];
} else {
self.currentID = [NSMutableString string];
}
}
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
if ([elementName isEqualToString:#"source"]) {
[self.overlays addObject:
[NSDictionary dictionaryWithObjectsAndKeys:self.currentID,#"id",nil]];
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
string = [string stringByReplacingOccurrencesOfString:#"\n" withString:#""];
string = [string stringByReplacingOccurrencesOfString:#"\t" withString:#""];
if ([self.currentElement isEqualToString:#"id"]) {
[self.currentID appendString:string];
}
}
- (void)parserDidEndDocument:(NSXMLParser *)parser {
self.currentID = nil;
}
You might also want to try Build&Analyse for your code. this may point out where you are leaking.