繁体   English   中英

简单而简洁的桌面Cocoa NSXMLParser示例?

[英]Simple and concise desktop Cocoa NSXMLParser example?

我想查看一个文件的元素,当一个特定元素出来时,输出标签之间的内容。

我试图按照名为事件驱动的XML编程的Mac Dev中的示例,但它没有完成得非常清楚。 它说要确保我对代理进行编码,但它从未显示过一个例子。 我只是想看一个简单的例子:

  • 假定该文件是一个很好的xml文件。
  • 它的路径是一个URL(或字符串)。
  • 解释了委托与解析器交互的方式。

许多Cocoa教程似乎几乎教你绕过委托类并制作自己的IBAction函数,所以我错过了我认为如何正确使用委托的培训。 在示例中我不清楚是否应该在委托类中构建委托或者使用解析器将它们保存在类中。

这是基于我最初编写的用于剪切长NSString的一部分的东西。 我将该iOS项目中的NSXMLParserDelegate代码复制到OS X项目中。 它从网页中的特定对象获取文本。

.h文件:

@interface so7576593AppDelegate : NSObject <NSApplicationDelegate, NSXMLParserDelegate> {
    NSWindow *window;
    IBOutlet NSTextField *textField;

    NSMutableString *divCharacters;
    BOOL captureCharacters; 
}

@property (assign) IBOutlet NSWindow *window;

@end

.m文件:

#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 

如果单击该页面上的“下一步”链接并转到“处理XML元素和属性”,它将为您提供如何对代理进行编码的示例。

Apple在ImageMap中提供了Mac示例。

Mac和iPhone上的NSXMLParser没有区别,因此阅读iPhone示例应该不是问题。

下面是一个在自定义类中使用NSXMLParser的示例,该类接受要查找的标记字符串和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

和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

像这样使用:

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

然后实现委托方法:

- (void)acceptParsedData:(NSMutableArray *)parsedData withIdent:(NSString *)ident {
    // do stuff here with the parsed data
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM