NSXMLParser 在找到第一个实例时停止
NSXMLParser Stops When It Finds The Very First Instance
我正在尝试使用 NSXMLParser 解析此 XML。我在 XML 文件中有多个 "Coffee" 实例,如下所示:
… More XML
<Coffee>
<Type Name="Type">Minimum Drinking Amount</Type>
</Coffee>
<Coffee>
<Type Name="Type">Maximum Drinking Amount</Type>
</Coffee>
… More XML
现在,一旦 NSXMLParser 找到 "Coffee" 的第一个实例,就完成并移动到 XML 的其余部分。哪个...好吧,这不是我想要的。我需要它来读取 "Coffee" 的每个实例 这就是我在 Objective-C.
中处理它的方式
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
NSLog(@"Fired Stick1");
_xmlString = elementName;
if ([_xmlString isEqualToString:@"Coffee"]) {
NSLog(@"Stick1 Coffee:");
}
if ([_xmlString isEqualToString:@"Tea"]) {
NSLog(@"Stick1 Tea:");
}
然后是 foundCharacters 委托:
-(void) parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
if ([_xmlString isEqualToString:@"Coffee"] || [_xmlString isEqualToString:@"Tea"]) {
NSLog@"%@ Called", _xmlString);
}
if (!_coffeeString) {
_coffeeString = [[NSMutableString alloc] initWithString:string];
}
else {
_coffeeString = string;
}
if (coffeeArray == NULL) {
NSLog(@"Stick1 the coffeeArray was null");
coffeeArray = [[NSMutableArray alloc] init];
}
//add the returned string into an array
[coffeeArray addObject:_coffeeString];
NSLog(@"Stick1 array %@", coffeeArray);
// parse the returned data in array
NSString *seperate = [coffeeArray componentsJoinedByString:@"\n"];
NSLog(@"Stick1 seperate is %@", seperate);
// another parsing
NSArray* words = [seperate componentsSeparatedByCharactersInSet :[NSCharacterSet whitespaceAndNewlineCharacterSet]];
//or use newLineCharecterSet
// Take out all of the whitespace like tabs and spaces and new lines
_singleName = [words componentsJoinedByString:@""];
NSLog(@"Stick1 final result %@", _singleName);
}
基本上,它被调用了两次,但不会显示两组数据。找到咖啡后,它会显示咖啡的第一部分(最小),但不会显示咖啡的第二个实例(最大)。
我认为您遇到了几个问题。其中之一是(至少使用提供的 XML),<Coffee>...</Coffee>
定义了整个 XML 文档,因此您可能遇到未处理的解析错误。您应该在 NSXMLParserDelegate
中执行以下代码并查看报告的问题:
- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError {
NSLog(@"error: %@", parseError);
}
- (void)parser:(NSXMLParser *)parser validationErrorOccurred:(NSError *)validationError {
NSLog(@"error: %@", validationError);
}
您还遇到问题,您试图根据节点的标签名称 (elementName
) 在您的代码中设置 trigger/flag,但您实际上关心包含的数据在子节点中。
此外,parser:foundCharacters:
NOT 保证 return 标签的全部内容都在一个字符串中,因此您最好处理 parser:didStartElement:...
和parser:didEndElement:...
。然后,在 parser:foundCharacters:
中,您可以确保您处于适当的节点中,并 追加 已找到的字符。
根据您提供的数据,这里有一些示例代码可以帮助您入门:
NOTE: I'm just taking a shot at what you actually want, since your data is a bit vague. Also, I did this in the App Delegate of a brand new Single View App. This is NOT the way to do a real implementation!
// AppDelegate.m
#import "AppDelegate.h"
@interface AppDelegate () <NSXMLParserDelegate> {
}
@property (assign, nonatomic) BOOL inNode;
@property (strong, nonatomic) NSMutableArray *coffeeArray;
@property (strong, nonatomic) NSMutableString *coffeeString;
@property (copy , nonatomic) NSString *singleName;
@property (copy , nonatomic) NSString *xmlString;
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSXMLParser *parser = [[NSXMLParser alloc] initWithData:[[self xml] dataUsingEncoding:NSUTF8StringEncoding]];
parser.delegate = self;
[parser parse];
return YES;
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
NSLog(@"Fired Stick1");
self.xmlString = elementName;
if ([self.xmlString isEqualToString:@"Coffee"]) {
NSLog(@"Stick1 Coffee:");
self.coffeeString = [[NSMutableString alloc] init];
self.inNode = YES;
} else if ([self.xmlString isEqualToString:@"Tea"]) {
NSLog(@"Stick1 Tea:");
self.coffeeString = [[NSMutableString alloc] init];
self.inNode = YES;
} else {
self.inNode = NO;
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
if (self.inNode == YES) {
if ([self.xmlString isEqualToString:@"Coffee"] || [self.xmlString isEqualToString:@"Tea"]) {
NSLog(@"%@ Called", self.xmlString);
}
[self.coffeeString appendString:string];
}
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
if ([elementName isEqualToString:@"Coffee"] || [elementName isEqualToString:@"Tea"]) {
if (self.coffeeArray == nil) {
NSLog(@"Stick1 the coffeeArray was null");
self.coffeeArray = [[NSMutableArray alloc] init];
}
//add the returned string into an array
[self.coffeeArray addObject:self.coffeeString];
NSLog(@"Stick1 array %@", self.coffeeArray);
// parse the returned data in array
NSString *seperate = [self.coffeeArray componentsJoinedByString:@"\n"];
NSLog(@"Stick1 seperate is %@", seperate);
// another parsing
NSArray* words = [seperate componentsSeparatedByCharactersInSet :[NSCharacterSet whitespaceAndNewlineCharacterSet]];
//or use newLineCharecterSet
// Take out all of the whitespace like tabs and spaces and new lines
_singleName = [words componentsJoinedByString:@""];
NSLog(@"Stick1 final result %@", _singleName);
}
}
- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError {
NSLog(@"error: %@", parseError);
}
- (void)parser:(NSXMLParser *)parser validationErrorOccurred:(NSError *)validationError {
NSLog(@"error: %@", validationError);
}
- (NSString *)xml {
NSMutableString *xml = [[NSMutableString alloc] init];
[xml appendString:@"<Document>"];
[xml appendString:@""
@"<Coffee>"
@" <Type Name=\"Type\">"
@" Minimum Drinking Amount"
@" </Type>"
@"</Coffee>"
@"<Coffee>"
@" <Type Name=\"Type\">"
@" Maximum Drinking Amount"
@" </Type>"
@"</Coffee>\n"];
[xml appendString:@""
@"<Coffee>"
@" <Type Name=\"Type\">"
@" Minimum Drinking Amount"
@" </Type>"
@"</Coffee>"
@"<Coffee>"
@" <Type Name=\"Type\">"
@" Maximum Drinking Amount"
@" </Type>"
@"</Coffee>\n"];
[xml appendString:@""
@"<Coffee>"
@" <Type Name=\"Type\">"
@" Minimum Drinking Amount"
@" </Type>"
@"</Coffee>"
@"<Coffee>"
@" <Type Name=\"Type\">"
@" Maximum Drinking Amount"
@" </Type>"
@"</Coffee>\n"];
[xml appendString:@""
@"<Coffee>"
@" <Type Name=\"Type\">"
@" Minimum Drinking Amount"
@" </Type>"
@"</Coffee>"
@"<Coffee>"
@" <Type Name=\"Type\">"
@" Maximum Drinking Amount"
@" </Type>"
@"</Coffee>\n"];
[xml appendString:@""
@"<Coffee>"
@" <Type Name=\"Type\">"
@" Minimum Drinking Amount"
@" </Type>"
@"</Coffee>"
@"<Coffee>"
@" <Type Name=\"Type\">"
@" Maximum Drinking Amount"
@" </Type>"
@"</Coffee>\n"];
[xml appendString:@""
@"<Coffee>"
@" <Type Name=\"Type\">"
@" Minimum Drinking Amount"
@" </Type>"
@"</Coffee>"
@"<Coffee>"
@" <Type Name=\"Type\">"
@" Maximum Drinking Amount"
@" </Type>"
@"</Coffee>\n"];
[xml appendString:@"</Document>"];
return [xml copy];
}
@end
我正在尝试使用 NSXMLParser 解析此 XML。我在 XML 文件中有多个 "Coffee" 实例,如下所示:
… More XML
<Coffee>
<Type Name="Type">Minimum Drinking Amount</Type>
</Coffee>
<Coffee>
<Type Name="Type">Maximum Drinking Amount</Type>
</Coffee>
… More XML
现在,一旦 NSXMLParser 找到 "Coffee" 的第一个实例,就完成并移动到 XML 的其余部分。哪个...好吧,这不是我想要的。我需要它来读取 "Coffee" 的每个实例 这就是我在 Objective-C.
中处理它的方式- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
NSLog(@"Fired Stick1");
_xmlString = elementName;
if ([_xmlString isEqualToString:@"Coffee"]) {
NSLog(@"Stick1 Coffee:");
}
if ([_xmlString isEqualToString:@"Tea"]) {
NSLog(@"Stick1 Tea:");
}
然后是 foundCharacters 委托:
-(void) parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
if ([_xmlString isEqualToString:@"Coffee"] || [_xmlString isEqualToString:@"Tea"]) {
NSLog@"%@ Called", _xmlString);
}
if (!_coffeeString) {
_coffeeString = [[NSMutableString alloc] initWithString:string];
}
else {
_coffeeString = string;
}
if (coffeeArray == NULL) {
NSLog(@"Stick1 the coffeeArray was null");
coffeeArray = [[NSMutableArray alloc] init];
}
//add the returned string into an array
[coffeeArray addObject:_coffeeString];
NSLog(@"Stick1 array %@", coffeeArray);
// parse the returned data in array
NSString *seperate = [coffeeArray componentsJoinedByString:@"\n"];
NSLog(@"Stick1 seperate is %@", seperate);
// another parsing
NSArray* words = [seperate componentsSeparatedByCharactersInSet :[NSCharacterSet whitespaceAndNewlineCharacterSet]];
//or use newLineCharecterSet
// Take out all of the whitespace like tabs and spaces and new lines
_singleName = [words componentsJoinedByString:@""];
NSLog(@"Stick1 final result %@", _singleName);
}
基本上,它被调用了两次,但不会显示两组数据。找到咖啡后,它会显示咖啡的第一部分(最小),但不会显示咖啡的第二个实例(最大)。
我认为您遇到了几个问题。其中之一是(至少使用提供的 XML),<Coffee>...</Coffee>
定义了整个 XML 文档,因此您可能遇到未处理的解析错误。您应该在 NSXMLParserDelegate
中执行以下代码并查看报告的问题:
- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError {
NSLog(@"error: %@", parseError);
}
- (void)parser:(NSXMLParser *)parser validationErrorOccurred:(NSError *)validationError {
NSLog(@"error: %@", validationError);
}
您还遇到问题,您试图根据节点的标签名称 (elementName
) 在您的代码中设置 trigger/flag,但您实际上关心包含的数据在子节点中。
此外,parser:foundCharacters:
NOT 保证 return 标签的全部内容都在一个字符串中,因此您最好处理 parser:didStartElement:...
和parser:didEndElement:...
。然后,在 parser:foundCharacters:
中,您可以确保您处于适当的节点中,并 追加 已找到的字符。
根据您提供的数据,这里有一些示例代码可以帮助您入门:
NOTE: I'm just taking a shot at what you actually want, since your data is a bit vague. Also, I did this in the App Delegate of a brand new Single View App. This is NOT the way to do a real implementation!
// AppDelegate.m
#import "AppDelegate.h"
@interface AppDelegate () <NSXMLParserDelegate> {
}
@property (assign, nonatomic) BOOL inNode;
@property (strong, nonatomic) NSMutableArray *coffeeArray;
@property (strong, nonatomic) NSMutableString *coffeeString;
@property (copy , nonatomic) NSString *singleName;
@property (copy , nonatomic) NSString *xmlString;
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSXMLParser *parser = [[NSXMLParser alloc] initWithData:[[self xml] dataUsingEncoding:NSUTF8StringEncoding]];
parser.delegate = self;
[parser parse];
return YES;
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
NSLog(@"Fired Stick1");
self.xmlString = elementName;
if ([self.xmlString isEqualToString:@"Coffee"]) {
NSLog(@"Stick1 Coffee:");
self.coffeeString = [[NSMutableString alloc] init];
self.inNode = YES;
} else if ([self.xmlString isEqualToString:@"Tea"]) {
NSLog(@"Stick1 Tea:");
self.coffeeString = [[NSMutableString alloc] init];
self.inNode = YES;
} else {
self.inNode = NO;
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
if (self.inNode == YES) {
if ([self.xmlString isEqualToString:@"Coffee"] || [self.xmlString isEqualToString:@"Tea"]) {
NSLog(@"%@ Called", self.xmlString);
}
[self.coffeeString appendString:string];
}
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
if ([elementName isEqualToString:@"Coffee"] || [elementName isEqualToString:@"Tea"]) {
if (self.coffeeArray == nil) {
NSLog(@"Stick1 the coffeeArray was null");
self.coffeeArray = [[NSMutableArray alloc] init];
}
//add the returned string into an array
[self.coffeeArray addObject:self.coffeeString];
NSLog(@"Stick1 array %@", self.coffeeArray);
// parse the returned data in array
NSString *seperate = [self.coffeeArray componentsJoinedByString:@"\n"];
NSLog(@"Stick1 seperate is %@", seperate);
// another parsing
NSArray* words = [seperate componentsSeparatedByCharactersInSet :[NSCharacterSet whitespaceAndNewlineCharacterSet]];
//or use newLineCharecterSet
// Take out all of the whitespace like tabs and spaces and new lines
_singleName = [words componentsJoinedByString:@""];
NSLog(@"Stick1 final result %@", _singleName);
}
}
- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError {
NSLog(@"error: %@", parseError);
}
- (void)parser:(NSXMLParser *)parser validationErrorOccurred:(NSError *)validationError {
NSLog(@"error: %@", validationError);
}
- (NSString *)xml {
NSMutableString *xml = [[NSMutableString alloc] init];
[xml appendString:@"<Document>"];
[xml appendString:@""
@"<Coffee>"
@" <Type Name=\"Type\">"
@" Minimum Drinking Amount"
@" </Type>"
@"</Coffee>"
@"<Coffee>"
@" <Type Name=\"Type\">"
@" Maximum Drinking Amount"
@" </Type>"
@"</Coffee>\n"];
[xml appendString:@""
@"<Coffee>"
@" <Type Name=\"Type\">"
@" Minimum Drinking Amount"
@" </Type>"
@"</Coffee>"
@"<Coffee>"
@" <Type Name=\"Type\">"
@" Maximum Drinking Amount"
@" </Type>"
@"</Coffee>\n"];
[xml appendString:@""
@"<Coffee>"
@" <Type Name=\"Type\">"
@" Minimum Drinking Amount"
@" </Type>"
@"</Coffee>"
@"<Coffee>"
@" <Type Name=\"Type\">"
@" Maximum Drinking Amount"
@" </Type>"
@"</Coffee>\n"];
[xml appendString:@""
@"<Coffee>"
@" <Type Name=\"Type\">"
@" Minimum Drinking Amount"
@" </Type>"
@"</Coffee>"
@"<Coffee>"
@" <Type Name=\"Type\">"
@" Maximum Drinking Amount"
@" </Type>"
@"</Coffee>\n"];
[xml appendString:@""
@"<Coffee>"
@" <Type Name=\"Type\">"
@" Minimum Drinking Amount"
@" </Type>"
@"</Coffee>"
@"<Coffee>"
@" <Type Name=\"Type\">"
@" Maximum Drinking Amount"
@" </Type>"
@"</Coffee>\n"];
[xml appendString:@""
@"<Coffee>"
@" <Type Name=\"Type\">"
@" Minimum Drinking Amount"
@" </Type>"
@"</Coffee>"
@"<Coffee>"
@" <Type Name=\"Type\">"
@" Maximum Drinking Amount"
@" </Type>"
@"</Coffee>\n"];
[xml appendString:@"</Document>"];
return [xml copy];
}
@end