Passing NULL value - objective-c

I use an instance of NSXMLParser. I store found chars in NSMutableStrings that are stored in an NSMutableDictionary and these Dicts are then added to an NSMutableArray.
When I test this everything seems normal: I count 1 array, x dictionnaries and x strings.
In a detailview controller file I want to show my parsed results. I call the class where everthing is stored but I get (null) returned.
This is what I do (wrong):
xAppDelegate.h
#interface xAppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
UINavigationController *navigationController;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet UINavigationController *navigationController;
#end
xAppDelegate.m
#import "xAppDelegate.h"
#import "RootViewController.h"
#import "XMLParser.h"
#implementation xAppDelegate
#synthesize window, navigationController;
- (void)applicationDidFinishLaunching:(UIApplication *)application {
// OFFLINE DOCUMENT > Resources folder
NSString *Path = [[NSBundle mainBundle] bundlePath];
NSString *DataPath = [Path stringByAppendingPathComponent:#"file.xml"];
NSData *Data = [[NSData alloc] initWithContentsOfFile:DataPath];
NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithData:Data];
XMLParser *parser = [[XMLParser alloc] initXMLParser];
[xmlParser setDelegate:parser];
[xmlParser setShouldProcessNamespaces:NO];
[xmlParser setShouldReportNamespacePrefixes:NO];
[xmlParser setShouldResolveExternalEntities:NO];
[xmlParser parse];
[window addSubview: navigationController.view];
[window makeKeyAndVisible];
}
- (void)dealloc {
[window release];
[navigationController release];
[super dealloc];
}
#end
XMLParser.h
#class xAppDelegate;
#interface XMLParser : NSObject {
NSMutableArray *array;
NSMUtableDictionary *dictionary;
NSSMutabletring *element;
xAppDelegate *appDelegate;
}
- (XMLParser *) initXMLParser;
#property (nonatomic, retain) NSMutableArray *array;
#property (nonatomic, retain) NSMutableDictionary *dictionary;
#property (nonatomic, retain) NSMutableString *element;
XMLParser.m
#import "xAppDelegate.h"
#import "XMLParser.h"
#synthesize array, dictionary, element;
- (XMLParser *) initXMLParser {
[super init];
appDelegate = (xAppDelegate *)[[UIApplication sharedApplication] delegate];
return self;
}
- (void)parserDidStartDocument:(NSXMLParser *)parser {
array = [[NSMutableArray alloc] init];
dictionary = [[NSMutableDictionary alloc] init];
}
- (void)parser:(NSXMLParser *)parser
didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName
attributes:(NSDictionary *)attributeDict
{
ele = [elementName copy];
if ([elementName isEqualToString:#"CONTAINER"]) {
element = [[NSMutableString alloc] init];
}
}
- (void)parser:(NSXMLParser *)parser
foundCharacters:(NSMutableString *)string
{
if ([ele isEqualToString:#"ELEMENTNAME"]) {
[element appendString:string];
}
}
- (void)parser:(NSXMLParser *)parser
didEndElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName
{
if ([elementName isEqualToString:#"CONTAINER"]) {
[dictionary setObject:element forKey:#"ELEMENTNAME"];
[array addObject:[dictionary copy]];
}
}
- (void) dealloc {
[element release];
[dictionary release];
[array release];
}
In my controller file I do this:
controller.h
#class XMLParser;
#interface controller : UIViewController {
XMLParser *aXMLParser;
}
#property (nonatomic, retain) XMLParser *aXMLParser;
controller.m
#import "XMLParser.h"
#synthesize aXMLParser;
- (void)viewDidLoad {
NSLog(#"test array: %#", aXMLParser.array);
NSLog(#"test dict: %#", aXMLParser.dictionary);
NSLog(#"test element: %#", aXMLParser.element);
}
When I test the value of my array, a dict or an element in the XMLParser.h file I get my result. What am I doing wrong so I can't call my results in my controller file?
Any help is welcome, because I'm pretty stuck right now :/

You probably haven't initialised the NSMutableString element, so you are probably sending messages to a nil object.
That's a guess because you haven't posted the important code. We need to see
where you initialise the three objects
where you assign them e.g. you might be assigning nil to one of them without realising it.
Edited following latest bit of code
There's quite a lot wrong with the code, for instance, it leaks a lot of objects, but I can't see anything that would cause your specific issue, unless the the ELEMENTNAME elements don't appear inside the CONTAINER elements in your XML.
I'm not an expert on user interface code on iPhone, but are you sure applicationDidFinishLaunching runs before viewDidLoad?
Also, you don't seem to ever assign your parser to the aXMLParser property.
Some of the Other Issues
Your NSXMLParser leaks because you don't release it.
Your own parser also leaks for the same reason (you probably just want to use aXMLParser, not a locally defined one).
Your initXMPLarser method should look like:
- (XMLParser *) initXMLParser {
self = [super init];
if (self != nil)
{
appDelegate = (xAppDelegate *)[[UIApplication sharedApplication] delegate];
}
return self;
}
i.e. don't throw away the result of [super init] and make sure it is not nil.
array is allocated every time you hit a new element. Each tilme you hit a new element, you throw away and leak the previous array from the last element.
dictionary is allocated every time you hit a CONTAINER element. You should at least release the old one before allocating the new one.
element also leaks.
The copy of dictionary you put into the array also leaks. Objective-C collections retain their elements.

Related

Accessing properties of objects in array to display in UITableViewCell

I am using an XML parser to get information from a blog to create a feed reader app. I created an object with properties that are the data for each blog entry (title, published, author...). I'm storing the data in the object, then using a pointer to put the object in an array of parsed data. When I go to access the properties to display them in my UITableView, every cell is the same, with the last blog entry's data for every one.
parser .m file
#interface Parser()
//This property holds the blog objects that were parsed
#property (nonatomic, strong) NSMutableArray *parsedResults;
//This property holds the current element content being parsed
#property (nonatomic, strong) NSString *currentElement;
#property (nonatomic, strong) FRFeedItem *blogEntry;
#end
#implementation SolsticeParser
#synthesize parsedResults = _parsedResults;
#synthesize currentElement = _currentElement;
// Will be used to truncate data parsed from publish tag so that it will only store the YYYY-MM-DD to self.blogEntry.datepublished
NSRange dateOnly = {0, 10};
//This method initializes the parser, sets the delegate, starts parsing, and returns the results.
- (NSMutableArray *)parseFeedWithResults:(NSURL *)URL
{
NSXMLParser *parser = [[NSXMLParser alloc] initWithContentsOfURL:URL];
parser.delegate = self;
self.parsedResults = [[NSMutableArray alloc] init];
[parser parse]; // Everything parsed here
return self.parsedResults;
}
...Here parsed data is saved to the properties of the BlogEntry object...
#pragma mark - Parser delegate
- (void)parser:(NSXMLParser *)parser
didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qualifiedName
attributes:(NSDictionary *)attributeDict
{
// Custom blog object initialized here
if ([elementName isEqualToString:#"entry"]) {
if (!self.blogEntry) {
self.blogEntry = [[FRFeedItem alloc] init];
}
}
}
...
- (void)parser:(NSXMLParser *)parser
didEndElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName {
if([elementName isEqualToString:#"title"]) {
self.blogEntry.title = self.currentElement;
} else if([elementName isEqualToString:#"published"]) {
self.blogEntry.datePublished = [self.currentElement substringWithRange:dateOnly];
} else if([elementName isEqualToString:#"entry"]) {
[self.parsedResults addObject:self.blogEntry];
}
}
In MyTableViewController.m:
#interface MyTableViewController ()
#property (nonatomic, strong) Parser* parser;
#property (nonatomic, strong) NSMutableArray* feedDataFromParser;
#end
#implementation MyTableViewController
// synthesize automatically done by Xcode v4.6
- (void)viewDidLoad
{
[super viewDidLoad];
self.parser = [[Parser alloc] init]; // initialize parser by allocating memory on the heap
[self loadItems]; // automatically loads data to be displayed upon opening the app
}
- (void)loadItems
{
// information parsed from blog stored to a mutable array
self.feedDataFromParser = [self.parser parseFeedWithResults:[NSURL URLWithString:kFeedURL]];
}
...
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//code not included for this question for brevity
// Configure the cell from data stored in mutable array of FRFeedItem objects
// PROBLEM:
cell.textLabel.text = [[self.feedDataFromParser objectAtIndex:indexPath.row] title];
cell.detailTextLabel.text = [[self.feedDataFromParser objectAtIndex:indexPath.row] datePublished];
return cell;
}
#end
As far as I can tell, there is nothing syntactically wrong. I've tried printing out the data parsed and saved to the object in the parser file as well as the value of indexPath.row, and both are correct.
What am I missing??
I think the problem is this line:
if (!self.blogEntry)
After you create the first one, you won't create any more. Try removing that if clause, and see if that fixes it.

Return the count of an NSMutableArray from an XML id number in Objective-C?

I am building an NSMutableArray out of an XML file and need to return the count of each resident id in the XML file. Is it possible to do this?
<residents>
<resident id="1">
<name>
<first>Daffy</first>
<last>Duck</last>
</name>
</resident>
<resident id="2">
<name>
<first>Mickey</first>
<last>Mouse</last>
</name>
</resident>
etc...
I will be returning the count using code similar to this:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSLog(#"Count = %i", [appDelegate.residents count]);
return [appDelegate.residents count];
Any suggestions?
For the array, in my AppDelegate.h I have:
#interface AppDelegate : UIResponder <UIApplicationDelegate>
{
UIWindow *window;
UINavigationController *navigationController;
NSMutableArray *residents;
}
#property (strong, nonatomic) UIWindow *window;
#property (nonatomic, retain) IBOutlet UINavigationController *navigationController;
#property (nonatomic, retain) NSMutableArray *residents;
In XMLAppDelegate.h I use:
#interface XMLAppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
UINavigationController *navigationController;
NSMutableArray *residents;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet UINavigationController *navigationController;
#property (nonatomic, retain) NSMutableArray *residents;
#end
You will need to use NSXMLParser (and NSXMLParserDelegate respectively) and correctly parse the XML data into the NSMutableArray before you can count anything. Also, to store everyday person's XML data, you may want to placing the information into NSMutableDictionaries.
In the .h #interface, you will need to create IVARs (example only):
#interface YourObject : UIViewController <NSXMLParserDelegate> {
NSXMLParser *parser;
NSString *currentElement;
NSMutableString *firstName;
NSMutableString *lastName;
NSMutableArray *residents;
}
and somewhere in the .m the code, call this:
NSString *xmlLocationString = #"http://www.website.com/feed.xml";
NSURL *xmlLocationURL = [NSURL URLWithString:xmlLocationString];
parser = [[NSXMLParser alloc] initWithContentsOfURL:xmlLocationURL];
[parser setDelegate:self];
[parser setShouldProcessNamespaces:NO];
[parser setShouldReportNamespacePrefixes:NO];
[parser setShouldResolveExternalEntities:NO];
[parser parse];
And of course, set up the delegate methods which will actually parse the XML document in to the NSMutableArray:
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{
currentElement = nil;
currentElement = [elementName copy];
if ([elementName isEqualToString:#"day"]) {
firstName = [[NSMutableString alloc]init];
lastName = [[NSMutableString alloc]init];
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
string = [string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
string = [string stringByTrimmingCharactersInSet:[NSCharacterSet controlCharacterSet]];
if ([currentElement isEqualToString:#"first"]) {
[firstName appendString:string];
} else if ([currentElement isEqualToString:#"last"]) {
[lastName appendString:string];
} else {
...
}
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
if ([elementName isEqualToString:#"day"]) {
NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] init];
[dictionary setObject:firstName forKey:#"fname"];
[dictionary setObject:lastName forKey:#"lname"];
//And finally
[residents addObject:dictionary];
}
}
Then, anywhere in your code you can call
[residents count];
to get the total count for the residents.
Notice: I just wrote this code as I went, it probably has some bugs
As of I understand you only need the count of . If so you can do following.
NSData *data = // your XML Data either from webservice or local file. Not xml string but the Data.
NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];
[parser setDelegate:self];
[parser parse];
This code will be where you get your data. In your .h file:
#interface yourViewController : UIViewController {
NSInteger resedintsCount;
}
in your .m File:
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{
if([elementName isEqualsToString:#"resident"]) {
resedintsCount++;
}
}
- (void)parserDidEndDocument:(NSXMLParser *)parser {
// you can use resedintsCount
}
I assumed that you are getting your XML data in view controller. If you are getting it in AppDelegate or any other class than even the same process will be there.
Still if you have in confusion feel free to ask.

Setting NSString variables with NSXMLParser

I am using NSXMLParser to grab information from an online XML file. My goal is to have one class do the XML parsing and another class to implement the variables. Below is the code for my project:
Current.h & Current.m
#import <Foundation/Foundation.h>
#interface Current : NSObject {
NSString *curTempF;
IBOutlet NSTextField *textField;
}
#property (nonatomic, copy) NSString *curTempF;
- (void)displayOutlets:(id)sender;
#end
and
#import "Current.h"
#implementation Current
#synthesize curTempF;
- (void)awakeFromNib {
[self displayOutlets:self];
}
- (void)displayOutlets:(id)sender {
[textField setStringValue:curTempF];
}
#end
XmlParser.h & XmlParser.m
#import <Foundation/Foundation.h>
#interface XmlParser : NSObject <NSXMLParserDelegate> {
NSString *urlString;
NSURL *url;
NSMutableString *xmlString;
}
- (IBAction)fetchXML:(id)sender;
#end
and
#import "XmlParser.h"
#import "Current.h"
#implementation XmlParser
- (void)awakeFromNib {
[self fetchXML:self];
}
- (IBAction)fetchXML:(id)sender {
urlString = #"http://api.wunderground.com/api/***/conditions/q/28173.xml";
url = [NSURL URLWithString:urlString];
NSXMLParser *parser = [[NSXMLParser alloc] initWithContentsOfURL:url];
[parser setDelegate:self];
[parser parse];
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
if ([elementName isEqual:#"temp_f"]) {
xmlString = [[NSMutableString alloc] init];
}
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
if ([elementName isEqual:#"temp_f"]) {
Current *cTempF = [[Current alloc] init];
[cTempF setCurTempF:xmlString];
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
[xmlString appendString:string];
}
#end
When I run the program I am receiving an error about "Invalid parameter not satisfying: aString". It looks like the setStringValue for the IBOutlet is not working. Any suggestions?
I suspect that when you initialize the Current class with [[Current alloc] init], it is trying to populate the textField with the curTempF string. However, the curTempF string is not initialized yet at that point until you call [cTempF setCurTempF:xmlString].
One approach would be to not display outlets in the Current class:
- (void)awakeFromNib {
//[self displayOutlets:self];
}
Then, call the displayOutlets function in your parser:
if ([elementName isEqual:#"temp_f"]) {
Current *cTempF = [[Current alloc] init];
[cTempF setCurTempF:xmlString];
[cTempF displayOutlets:cTempF];
}
Alternately, you could keep your awakeFromNib code the same, but create an initWith method in your Current class, which may be cleaner:
- (id) initWithCurTemp:(NSString *)curTemp {
self = [super init];
if (self) {
self.curTempF = curTemp;
}
return self;
}
- (void)awakeFromNib {
[self displayOutlets:self];
}
Then, your parser code would look like:
if ([elementName isEqual:#"temp_f"]) {
Current *cTempF = [[Current alloc] initWithCurTemp:xmlString];
}
You should create your Current in the nib, as you were doing, and not in code.
As for getting the parser (which I assume is in the same nib) to talk to the Current, create an outlet in the parser to point to the Current, and connect that outlet in the nib.

I can not parse xml from URL on objective c

I am a beginner in objective C , I want to parse a XML file from URL , I found some sample code about NSXMLPARSER and I write this code but it do not work.
please help me.
my xml file is :
<list>
<first>apple</first>
</list>
... My ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController <NSXMLParserDelegate> {
}
#property (weak, nonatomic) IBOutlet UITextView *myTextField;
#end
...My ViewController.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController #synthesize myTextField;
- (void)parseXMLFileAtURL:(NSString *)URL {
NSURL * xmlURL = [NSURL URLWithString:URL];
NSXMLParser * rssparser = [[NSXMLParser alloc] initWithContentsOfURL:xmlURL];
[rssparser setDelegate:self];
[rssparser parse];
}
- (void)parser:(NSXMLParser *)parser
didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName
attributes:(NSDictionary*)attributeDict {
if ([elementName isEqualToString:#"list"]) {
// clear out our story item caches...
myTextField.text = [attributeDict objectForKey:#"first"];
}
}
- (void)viewDidLoad {
NSString * path = #"http://example.com";
[self parseXMLFileAtURL:path];
[super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib.
}
- (void)viewDidUnload {
[self setMyTextField:nil];
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
#end
You shouldn't declare this is ViewController - is a very bad design. Create a new class (ex XMLParser: #interface XMLParser : NSObject <NSXMLParserDelegate>)
Now call in the initializer method parse. Below sample code:
-(id)init
{
self = [super init];
parser = [[NSXMLParser alloc] initWithContentsOfURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:#"guidef" ofType:#"xml"]]];
[parser setDelegate:self];
[parser parse];
return self;
}
Now you can declare your methods.
attributeDict holds only attribute values ...
<first name="something" last="something" > <sec>some</sec></first>
so when you get elementName as first attributeDict will have 'name' and 'last' and other attributes
not the child element sec

objectForKey error with NSXMLParser

I'm getting the following error:
"this class is not key value coding-compliant for the key temp_f"
my AppDelegate class files:
#import <Cocoa/Cocoa.h>
#interface AppDelegate : NSObject <NSApplicationDelegate> {
IBOutlet NSTableView *tableView;
NSArray *current;
}
#property (assign) IBOutlet NSWindow *window;
#end
#import "AppDelegate.h"
#import "CurrentWeather.h"
#import "XMLCurrent.h"
#implementation AppDelegate
#synthesize window = _window;
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
XMLCurrent *currentXML = [[XMLCurrent alloc] init];
NSError *error = nil;
current = [currentXML fetchCurrentWithError:&error];
[tableView reloadData];
}
- (NSInteger)numberOfRowsInTableView:(NSTableView *)theTableView {
return [current count];
}
- (id)tableView:(NSTableView *)theTableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
CurrentWeather *c = [current objectAtIndex:row];
return [c valueForKey:[tableColumn identifier]];
}
#end
my CurrentWeather class files:
#import <Foundation/Foundation.h>
#interface CurrentWeather : NSObject {
NSString *location;
NSString *weather;
NSString *degreesF;
}
#property (nonatomic, copy) NSString *location;
#property (nonatomic, copy) NSString *weather;
#property (nonatomic, copy) NSString *degreesF;
#end
#import "CurrentWeather.h"
#implementation CurrentWeather
#synthesize location, weather, degreesF;
#end
my XMLCurrent class files:
#import <Foundation/Foundation.h>
#interface XMLCurrent : NSObject <NSXMLParserDelegate> {
NSMutableArray *current;
NSMutableString *currentString;
NSMutableDictionary *currentFields;
}
- (NSArray *)fetchCurrentWithError:(NSError **)outError;
#end
#import "XMLCurrent.h"
#import "CurrentWeather.h"
#implementation XMLCurrent
- (id)init {
self = [super init];
if (self) {
current = [[NSMutableArray alloc] init];
}
return self;
}
- (NSArray *)fetchCurrentWithError:(NSError **)outError {
BOOL success;
NSURL *xmlURL = [NSURL URLWithString:#"http://www.weather.gov/xml/current_obs/KCLT.xml"];
NSURLRequest *req = [NSURLRequest requestWithURL:xmlURL cachePolicy:NSURLRequestReturnCacheDataElseLoad timeoutInterval:30];
NSURLResponse *resp = nil;
NSData *data = [NSURLConnection sendSynchronousRequest:req returningResponse:&resp error:outError];
if (!data) {
return nil;
}
[current removeAllObjects];
NSXMLParser *parser;
parser = [[NSXMLParser alloc] initWithData:data];
[parser setDelegate:self];
success = [parser parse];
if (!success) {
*outError = [parser parserError];
return nil;
}
NSArray *output = [current copy];
return output;
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName
attributes:(NSDictionary *)attributeDict {
if ([elementName isEqual:#"current_observation"]) {
currentFields = [[NSMutableDictionary alloc] init];
}
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName {
if ([elementName isEqual:#"current_observation"]) {
CurrentWeather *currentCond = [[CurrentWeather alloc] init];
[currentCond setLocation:[currentFields objectForKey:#"location"]];
[currentCond setWeather:[currentFields objectForKey:#"weather"]];
[currentCond setDegreesF:[currentFields objectForKey:#"temp_f"]];
[current addObject:currentCond];
currentCond = nil;
currentFields = nil;
} else if (currentFields && currentString) {
NSString *trimmed;
trimmed = [currentString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
[currentFields setObject:trimmed forKey:elementName];
}
currentString = nil;
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
if (!currentString) {
currentString = [[NSMutableString alloc] init];
}
[currentString appendString:string];
}
#end
The keys are used as the "identifier" in a table view. For some reason, if the key has an underscore in it (such as temp_f) I get an error. The underscore is necessary because it is the name of the element in the XML file. If there is no underscore, then no error. How can I get data from an XML element that contains an underscore?
The xml data is being parsed from http://www.weather.gov/xml/current_obs/KCLT.xml
CurrentWeather has a degreesF property, which you set from the temp_f XML field. You need to set the identifier for the table column to "degreesF" not "temp_f". This has nothing to do with temp_f containing an underscore. Rather, the problem is that CurrentWeather isn't Key Value Coding compliant for the key "temp_f" (just as the error states) because it doesn't have a property named "temp_f".
Explaining in further detail, in your -tableView:objectValueForTableColumn: method, you use the column's identifier as a key into a CurrentWeather instance. Since the identifier is "temp_f", you're doing this: [c valueForKey:#"temp_f"]. That throws an exception because CurrentWeather doesn't have a temp_f property.