【问题标题】:NSScanner Loop QuestionNSScanner 循环问题
【发布时间】:2011-09-13 11:59:21
【问题描述】:

我有一个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;
}

【问题讨论】:

    标签: iphone objective-c nsscanner


    【解决方案1】:

    不要使用扫描仪来解析 HTML(也不要使用正则表达式......哦,痛苦)*。 HTML 的全部意义在于它是一个结构化文档,旨在作为节点或对象树进行遍历。几乎整个基于 DOM [文档对象模型] 的行业都是围绕这一点构建的。

    只需使用 XML 解析器 [结构良好的 HTML 确实只是 XML]。 NSXMLDocument(或者——如果你需要事件驱动——NSXMLParser)会很有效。

    或者,如果您必须处理格式错误的 HTML(即任意服务器污水),请使用适当的 HTML 解析器。

    这个question/answer describes exactly that,有一个可靠的例子。

    *更不用说解析HTML在业界是一个“已解决的问题”。无需推出新的。

    【讨论】:

    • 这就是你使用 libxml2 的 HTML4 解析器的原因......任何时候有人说“HTML 不是 XML”,他们通常指的是缺乏强制的适当标签结构,libxml2 应该注意这一点.
    • HTML 和 XHTML 之间的区别不仅仅是强制结束标记(或自闭合标记)。所以“结构良好的 HTML 无论如何实际上只是 XML”听起来不太准确。 HTML 可以结构良好,但仍然不是 XML。无论如何,我同意最好使用 HTML 解析器。
    【解决方案2】:

    免责声明:要解析 HTML,最好使用像 libxml 的 HTML 4 解析器这样的 HTML 解析器,尤其是处理任意可能格式错误的 HTML。无论如何,由于问题询问如何使用NSParser 改进现有代码,我提供以下示例。这在大多数情况下都有效,但在某些极端情况下不会。对于 seriuos 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];
    

    【讨论】:

    • 在任何数量的完全有效的情况下都会失败;例如&lt;p class="header"&gt;...&lt;/p&gt;&lt;p&gt; This is a &lt;p&gt;paragraph in a paragraph&lt;/p&gt;.&lt;/p&gt;
    • 我编辑了代码以考虑@bbum 建议的元素属性。关于嵌套段落,我认为它们不是有效的 html。
    • 是的——你是对的。 &lt;p&gt;f&lt;p&gt;d&lt;/p&gt;c&lt;/p&gt; 无效...但是,在解析任意 HTML 时,“有效”通常表示“无论浏览器当前做什么”,结构有效性并不是真正需要考虑的因素。
    • 另外——IIRC,&lt;p 可能包含一段 javascript,其中可能包含未编码的 &lt;p 序列...
    • 我编辑了这个问题以反映使用 HTML 解析器会更好
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-23
    • 2018-11-05
    • 2013-10-06
    • 2021-11-25
    相关资源
    最近更新 更多