views:

168

answers:

4

I am working with an API where I get a response back this this, and I want to parse the integer ID out of it:

<?xml version="1.0"?>
<trip>328925</trip>

How would you parse this? I have some really fragile code I want to get rid of, and I'd appreciate some advice:

if ([[response substringWithRange:NSMakeRange(0, 21)] 
    isEqualToString: @"<?xml version=\"1.0\"?>"]) {

  self.tripId = [response substringWithRange:NSMakeRange(28, response.length-35)];
}

I don't think I need an XML parsing library for this task!

A: 

Check out 'NSScanner'. It would be perfect for this.

kubi
A: 
Mark
A: 

If you really don't want to use an XML Parser to create a proper object why not use the regular expression <trip>\d*</trip> to match the element? Then you can get the integer part by removing the start and end tag and parsing to ensure correct as with any string.

Here is a handy place for testing regular expressions; http://regexlib.com/RETester.aspx

Dave Anderson
+4  A: 

I would use an XML parser. Using an XML parser really is the best way to parse XML.

It's not that hard to do either:

// Parser Delegate
@interface ParserDelegate : NSObject {
    int inTripElements;
    NSMutableString* trip;
}
@property (readonly) NSMutableString* trip;
@end

@implementation ParserDelegate

@synthesize trip;

- (id) init {
    if (![super init]) {
        [self release];
        return nil;
    }
    trip = [@"" mutableCopy];
    return self;
}

- (void) parser:(NSXMLParser *)parser
didStartElement:(NSString *)elementName
   namespaceURI:(NSString *)namespaceURI
  qualifiedName:(NSString *)qualifiedName
     attributes:(NSDictionary *)attributeDict {
    if ([elementName isEqualToString:@"trip"]) {
        ++inTripElements;
    }
}

- (void) parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
    if (inTripElements > 0) {
        [trip appendString:string];        
    }
}

- (void) parser:(NSXMLParser *)parser
  didEndElement:(NSString *)elementName
   namespaceURI:(NSString *)namespaceURI
  qualifiedName:(NSString *)qName {
    if ([elementName isEqualToString:@"trip"]) {
        --inTripElements;
    }
}

@end


// Parsing
NSString* toParse = @"<?xml version=\"1.0\"?>"
                          "<trip>328925</trip>";

NSData* data = [NSData dataWithBytes:[toParse UTF8String]
                                 length:strlen([toParse UTF8String])];

ParserDelegate* parserDelegate = [[ParserDelegate alloc] init];
NSXMLParser* parser = [[NSXMLParser alloc] initWithData:data];

[parser setDelegate:parserDelegate];
[parser parse];
[parser release];

NSLog(@"trip=%@", parserDelegate.trip);
[parserDelegate release];
Will Harris
Thanks, your answer is perfect. I actually found a tutorial in the meantime that led me to write pretty much the same code: http://weblog.bignerdranch.com/?p=48
Andrew Johnson