我有一个NSScanner
对象,它在HTML文档中扫描段落标记。扫描仪似乎在找到第一个结果时就停止了,但我需要一个数组中的所有结果。
如何改进我的代码以浏览整个文档?
- (NSArray *)getParagraphs:(NSString *) html
{
NSScanner *theScanner;
NSString *text = nil;
theScanner = [NSScanner scannerWithString: html];
NSMutableArray*paragraphs = [[NSMutableArray alloc] init];
// find start of tag
[theScanner scanUpToString: @"<p>" intoString: NULL];
if ([theScanner isAtEnd] == NO) {
NSInteger newLoc = [theScanner scanLocation] + 10;
[theScanner setScanLocation: newLoc];
// find end of tag
[theScanner scanUpToString: @"</p>" intoString: &text];
[paragraphs addObject:text];
}
return text;
}
不要使用扫描仪来解析HTML(也不要使用正则表达式……哦,太痛苦了)*。HTML的全部意义在于,它是一个结构化文档,设计为作为节点或对象的树进行遍历。几乎整个基于DOM(文档对象模型)的行业都是围绕这一点构建的。
只要使用XML解析器就可以了[结构良好的HTML实际上就是XML]。NSXMLDocument(或者——如果您需要事件驱动的——NSXMLParser)将非常有效。
或者,如果您必须处理格式错误的HTML(即任意服务器污水),请使用适当的HTML解析器。
这个问题/答案正好描述了这一点,并提供了一个坚实的例子。
*更不用说解析HTML在业界是一个"已解决的问题"。没有必要推出新的。
免责声明:要解析HTML,最好使用像libxml的HTML 4解析器这样的HTML解析器,尤其是处理任意可能格式错误的HTML。无论如何,由于问题是询问如何使用NSParser
改进现有代码,因此我提供以下示例。这在大多数情况下都会起作用,但也有一些情况下不会。对于串行HTML解析,请使用HTML解析器。
重复,直到扫描仪用完所有字符:
NSScanner* scanner = [NSScanner scannerWithString:html];
NSMutableArray *paragraphs = [[NSMutableArray alloc] init];
[scanner scanUpToString:@"<p" intoString:nil];
while (![scanner isAtEnd]) {
[scanner scanUpToString:@">" intoString:nil];
[scanner scanString:@">" intoString:nil];
NSString * text = nil;
[scanner scanUpToString:@"</p>" intoString:&text];
if (text) { // if html contains empty paragraphs <p></p>, text could be nil
[paragraphs addObject:text];
}
[scanner scanUpToString:@"<p" intoString:nil];
}
...
[paragraphs release];