Simple and concise desktop Cocoa NSXMLParser example?

后端 未结 3 1699
梦如初夏
梦如初夏 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: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 
    @optional
    - (void)acceptParsedData:(NSMutableArray *)parsedData withIdent:(NSString *)ident;
    - (void)acceptParsedDebugData:(NSMutableArray *)parsedData withIdent:(NSString *)ident;
    
    @end
    
    @class JHKeyValuePair;
    
    @interface JHXMLParser : NSObject  {
        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 )delegate;
    - (void)setDelegate:(id )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 )delegate {
        id  d = nil;
        if (_delegate) {
            d = _delegate;
        }
        return d;
    }
    - (void)setDelegate:(id )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
    }
    

提交回复
热议问题