• charactersFound方法中的陷阱


    libxml2恐怕是linux下最著名的xml解析库了,其sax API不仅解析效率高,速度快,而且内存占用率更是出奇的低。因此是iphone开发中必不可少的xml解析库。

    但sax解析是基于事件驱动的,使用门槛较dom解析为高,不容易为初学者掌握,代码难于阅读和理解。比如笔者写过这样的代码:

    //解析元素体时触发

    - (void)charactersFound:(const xmlChar*)ch

    len:(int)len

    {       

    NSString*   string;

    string = [[NSString alloc] initWithBytes:ch length:len encoding:NSUTF8StringEncoding];

        // login_status元素体

        switch (flag) {

    case 1:

    [item setObject:string forKey:@"GNID"];

    break;

    case 2:

    [item setObject:string forKey:@"YWBH"];

    break;

    case 3:

    [item setObject:string forKey:@"QDRQ"];

    break;

        }

    }

    表面上看这段代码没有任何问题,实际上却隐藏着致命的陷阱。
    这是因为,当libxml2在解析一个元素体时,会不只一次的回调charactersFound方法!
    也就是说一个元素,需要好几次的回调,libxml才会解析出元素体文本。
    具体说,标签体文本如果包含多种编码(比如:ipcc日报,同时包含两种字符:asciiutf8编码),那么,libxml2会在解析“ipcc”时调用一次charactersFound方法,然后在“日报”两个字时再次回调charactersFound方法。
    因此上面的代码应该做如下修改:
    把局部变量string声明为全局的NSMutableString类型。
    修改上述方法代码为:

    - (void)charactersFound:(const xmlChar*)ch

    len:(int)len

    {       

    [string appendString:[[NSString alloc] initWithBytes:ch length:len encoding:NSUTF8StringEncoding]];

    }
    然后在元素结束标记回调方法中取得整个string的内容:

    //解析元素结束标记时触发

    - (void)endElementLocalName:(const xmlChar*)localname

    prefix:(const xmlChar*)prefix URI:(const xmlChar*)URI

    {

    switch (flag) {

    case 1:

    [item setObject:string forKey:@"GNID"];

    break;

    case 2:

    [item setObject:string forKey:@"YWBH"];

    break;

    case 3:

    [item setObject:string forKey:@"QDRQ"];

    break;

    }

    flag=0;

    }

    然后在元素开始标记回调方法startElementLocalName中,重置string变量:

    [string release];

        string=[[NSMutableString alloc]init];


  • 相关阅读:
    Java NIO使用及原理分析(二)(转)
    Java NIO使用及原理分析 (一)(转)
    虚拟机字节码执行引擎
    虚拟机类加载机制
    浅析Java中的final关键字
    java内存模型7-处理器内存模型
    java内存模型6-final
    最小生成树
    有向图的基本算法
    并查集(Union-Find)算法介绍
  • 原文地址:https://www.cnblogs.com/encounter/p/2188524.html
Copyright © 2020-2023  润新知