【问题标题】:Simple and concise desktop Cocoa NSXMLParser example?简单简洁的桌面 Cocoa NSXMLParser 示例?
【发布时间】:2011-09-27 22:56:30
【问题描述】:

我想浏览一个文件的元素,当一个特定的元素出现时,输出标签之间的内容。

我尝试按照 Mac Dev 中题为 Event Driven XML Programming 的示例进行操作,但它并没有很清楚地完成。它说要确保我对代表进行编码,但它从未显示示例。我只想看一个简单的例子:

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

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

【问题讨论】:

  • 这听起来像是一个很长的抱怨。你能把它改写成一个问题吗?说“没有好的教程”不是问题。寻求解决某些特定需求的教程会更好。我敢肯定那里有需要。也许与代表的简单示例有关?
  • 抱歉,我找不到任何关于 NSXMLParser for Objective C 的编写良好的教程。你能推荐一个可以帮助我的链接吗?是的,经过 8 小时的挫折,这是一个很长的抱怨。
  • “经过 8 小时的挫折”。虽然您有我们的同情,但长时间的抱怨并不能代替一个简单、清晰、重点突出的问题。请专注于您想要的事情。描述那个。不是你的糟糕经历。

标签: objective-c cocoa nsxmlparser sax


【解决方案1】:

这是基于我最初为Cut out a part of a long NSString 写的东西。我将 NSXMLParserDelegate 代码从那个 iOS 项目复制到一个 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 

【讨论】:

  • 非常感谢。我能够把它连接起来,我花了很多时间来理解它。现在我可以在此基础上尝试更复杂的了。
【解决方案2】:

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

Apple 在ImageMap 中提供了一个 Mac 示例。

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

【讨论】:

    【解决方案3】:

    这是一个在自定义类中使用 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
    }
    

    【讨论】:

      猜你喜欢
      • 2014-03-14
      • 2011-07-30
      • 2016-12-17
      • 2011-08-25
      • 1970-01-01
      • 2013-11-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多