Simple and concise desktop Cocoa NSXMLParser example?

后端 未结 3 1609
梦如初夏
梦如初夏 2021-01-25 07:54

I would like to look through the elements of a file and when one specific element comes out, output the contents in between the tag.

I tried to follow the example in the

相关标签:
3条回答
  • 2021-01-25 08:27

    If you click the "Next" link on that page and go onto "Handling XML Elements and Attributes" it will give you an example of how to code the delegates.

    Apple provides a Mac example in ImageMap.

    There's no difference between NSXMLParser on Mac and iPhone, so reading an iPhone example shouldn't be a problem.

    0 讨论(0)
  • 2021-01-25 08:33

    This is based on something I originally wrote for Cut out a part of a long NSString. I copied the NSXMLParserDelegate code from that iOS project into an OS X project. It gets the text from a specific object in a web page.

    .h file:

    @interface so7576593AppDelegate : NSObject <NSApplicationDelegate, NSXMLParserDelegate> {
        NSWindow *window;
        IBOutlet NSTextField *textField;
    
        NSMutableString *divCharacters;
        BOOL captureCharacters; 
    }
    
    @property (assign) IBOutlet NSWindow *window;
    
    @end
    

    .m file:

    #import "so7576593AppDelegate.h"
    
    @implementation so7576593AppDelegate
    
    @synthesize window;
    
    - (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
        captureCharacters = NO;
        NSURL *theURL = [NSURL URLWithString:@"http://maxnerios.yolasite.com/"];
        NSXMLParser *parser = [[NSXMLParser alloc] initWithContentsOfURL:theURL];
        [parser setDelegate:self];
        [parser parse];
        [parser release];
    
    }
    
    - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict {
        if ([elementName isEqual:@"div"] && [[attributeDict objectForKey:@"id"] isEqual:@"I3_sys_txt"]) {
            captureCharacters = YES;
            divCharacters = [[NSMutableString alloc] initWithCapacity:500];
        }
    }
    
    - (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
        if (captureCharacters) {
            //from parser:foundCharacters: docs:
            //The parser object may send the delegate several parser:foundCharacters: messages to report the characters of an element. 
            //Because string may be only part of the total character content for the current element, you should append it to the current 
            //accumulation of characters until the element changes.
            [divCharacters appendString:string];
        }
    }
    
    - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
        if (captureCharacters) {
            captureCharacters = NO;
            [textField setStringValue:divCharacters];
            [divCharacters release];
        }
    }
    
    @end 
    
    0 讨论(0)
  • 2021-01-25 08:40

    Here is an example of using an NSXMLParser in a custom class that takes in a string of the tag to look for and the xml NSData:

    JHXMLParser.h:

    @protocol JHXMLParserDelegate <NSObject>
    @optional
    - (void)acceptParsedData:(NSMutableArray *)parsedData withIdent:(NSString *)ident;
    - (void)acceptParsedDebugData:(NSMutableArray *)parsedData withIdent:(NSString *)ident;
    
    @end
    
    @class JHKeyValuePair;
    
    @interface JHXMLParser : NSObject <NSXMLParserDelegate> {
        NSString *ident;
    
        @private
        id _delegate;
        NSMutableArray *_parsedData;
        NSString *_key;
        NSData *_rawData;
        NSXMLParser *_dataParser;
        NSString *_previousTag;
        NSString *_currentTag;
    }
    
    @property (retain, nonatomic) NSString *ident;
    
    - (id)initWithKeyValuePair:(JHKeyValuePair *)kvPair;
    - (id)initWithKey:(NSString *)Key andData:(NSData *)data;
    // delegate management. The delegate is not retained.
    - (id <JHXMLParserDelegate>)delegate;
    - (void)setDelegate:(id <JHXMLParserDelegate>)delegate;
    - (BOOL)start;
    
    @end
    

    And the JHXMLParser.m:

    #import "JHKeyValuePair.h"
    #import "JHXMLParser.h"
    
    @implementation JHXMLParser
    
    @synthesize ident;
    
    - (id)init {
        if ((self = [super init])) {
            ident = [[NSString alloc] init];
        }
        return self;
    }
    
    - (id)initWithKeyValuePair:(JHKeyValuePair *)kvPair {
        if ((self = [self init])) {
            _key = [kvPair key];
            _rawData = [kvPair value];
            _dataParser = [[NSXMLParser alloc] initWithData:_rawData];
            _dataParser.delegate = self;
        }
        return self;
    }
    
    - (id)initWithKey:(NSString *)key andData:(NSData *)data {
        if ((self = [self init])) {
            _key = key;
            _rawData = data;
            _dataParser = [[NSXMLParser alloc] initWithData:_rawData];
            _dataParser.delegate = self;
        }
        return self;
    }
    
    - (id <JHXMLParserDelegate>)delegate {
        id <JHXMLParserDelegate> d = nil;
        if (_delegate) {
            d = _delegate;
        }
        return d;
    }
    - (void)setDelegate:(id <JHXMLParserDelegate>)delegate {
        _delegate = delegate;
    }
    
    - (BOOL)start {
        return [_dataParser parse];
    }
    
    - (void)dealloc {
        [_parsedData release];
        [_rawData release];
        [super dealloc];
    }
    
    #pragma mark - NSXMLParser Delegate
    
    - (void)parserDidStartDocument:(NSXMLParser *)parser {
        _parsedData = [[NSMutableArray alloc] init];
    }
    
    - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict {
        _currentTag = elementName;
        if ([elementName isEqualToString:_key]) {
            NSMutableDictionary *tmpDict = [[NSMutableDictionary alloc] init];
            [_parsedData addObject:tmpDict];
            [tmpDict release];
        }
    }
    
    - (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
        if (![_previousTag isEqualToString:_currentTag]) {
            [[_parsedData lastObject] setObject:[string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]
                                         forKey:_currentTag];
        } else {
            [[_parsedData lastObject] setObject:[NSString stringWithFormat:@"%@%@",[[_parsedData lastObject] objectForKey:_currentTag], [string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]] 
                                         forKey:_currentTag];
        }
        if (_previousTag) {
            [_previousTag release];
            _previousTag = nil;
        }
        _previousTag = [[NSString alloc] initWithFormat:@"%@", _currentTag];
        [pool drain];
    }
    
    - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
        if (![_previousTag isEqualToString:elementName]) {
            [[_parsedData lastObject] setObject:@"" forKey:elementName];
        } else {
            if (_previousTag) {
                [_previousTag release];
                _previousTag = nil;
            }
            _previousTag = [[NSString alloc] initWithFormat:@""];
        }
        [pool drain];
    }
    
    - (void)parserDidEndDocument:(NSXMLParser *)parser {
        if ([_delegate respondsToSelector:@selector(acceptParsedData:withIdent:)]) {
            [_delegate acceptParsedData:_parsedData withIdent:ident];
        } else if ([_delegate respondsToSelector:@selector(acceptParsedDebugData:withIdent:)]) {
            [_delegate acceptParsedDebugData:_parsedData withIdent:ident];
        }
    }
    
    - (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError {
    #ifdef DEBUG
        DEBUGLOG(@"Parser ERROR Occurred: %@", self.ident);
        DEBUGLOG(@"ERROR: %@", parseError);
    #endif
        if ([_delegate respondsToSelector:@selector(acceptParsedData:withIdent:)]) {
            [_delegate acceptParsedData:_parsedData withIdent:ident];
        } else if ([_delegate respondsToSelector:@selector(acceptParsedDebugData:withIdent:)]) {
            [_delegate acceptParsedDebugData:_parsedData withIdent:ident];
        }
    }
    
    @end
    

    Used like so:

    parser = [[[JHXMLParser alloc] initWithKey:@"INFO" andData:connectData] autorelease];
    parser.ident = @"INFO";
    parser.delegate = self;
    [parser start];
    

    Then implement the delegate method:

    - (void)acceptParsedData:(NSMutableArray *)parsedData withIdent:(NSString *)ident {
        // do stuff here with the parsed data
    }
    
    0 讨论(0)
提交回复
热议问题