天天看点

iOS开发之XML解析

本文利用苹果自带的、基于SAX的解析器:NSXMLParser和基于libxml2的DOM方式的GDataXML解析本地XML文件。前者也就是所谓的“事件驱动”的解析器。

新建项目,向项目中添加一个.xml文件,如下xml文件:

<books>
    <book id = "1">
        <title>西游记</title>
        <author>吴承恩</author>
        <remark>孙悟空</remark>
    </book>
    <book id = "2">
        <title>红楼梦</title>
        <author>曹雪芹</author>
        <remark>林黛玉</remark>
    </book>
    <book id = "3">
        <title>水浒传</title>
        <author>施耐庵</author>
        <remark>林冲</remark>
    </book>
    <book id = "4">
        <title>三国演义</title>
        <author>罗贯中</author>
        <remark>曹操</remark>
    </book>
</books>
           

在控制器.m文件中提前声明两个变量:

HXBook *book;// 模型

NSString*currentString;// 当前解析到的元素之间的字符内容

在控制器view加载完毕后,加载xml文件,并利用xml文件创建NSXMLParser对象,设置代理,再调用NSXMLParser对象的parse方法开始解析。如下:

- (void)viewDidLoad {
    [super viewDidLoad];
    //    NSURL *pathURL = [[NSBundle mainBundle] URLForResource:@"text" withExtension:@"xml"];

    NSString *path = [[NSBundle mainBundle] pathForResource:@"text.xml" ofType:nil];
    NSData *data = [NSData dataWithContentsOfFile:path];
    
    // 根据xml文件创建NSXMLParser对象
//    NSXMLParser *parser = [[NSXMLParser alloc] initWithContentsOfURL:pathURL];
    NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];
    
    // 设置代理
    parser.delegate = self;
    
    // 开始解析(SAX解析)
    [parser parse];
}
#pragma mark NSXMLParserDelegate
/**
 *  当扫描到文档的开始时调用(开始解析)
 */
- (void)parserDidStartDocument:(NSXMLParser *)parser {
    NSLog(@"开始解析");
}

/**
 *  当扫描到文档的结尾时调用(结束解析)
 */
- (void)parserDidEndDocument:(NSXMLParser *)parser {
    NSLog(@"结束解析");
    
    for (HXBook *b in self.books) {
        NSLog(@"书:%@", b.remark);
    }
}


/**
 *  当扫描到一个元素的开始时候调用(attributeDict存放着元unsude属性)
 */
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary<NSString *,NSString *> *)attributeDict {
    NSLog(@"开始处理元素:%@", elementName);
    
    if ([elementName isEqualToString:@"book"]) {
        // 创建模型
        book = [[HXBook alloc] init];
        book.ID = [[attributeDict objectForKey:@"id"] integerValue];
    }
    
    
}

/**
 *  解析到元素间的字符内容时调用
 */
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
    
    NSLog(@"处理的字符内容:%@", string);
    // 如果当前字符内容不为nil,则保存当前字符内容
    if (string) {
        currentString = string;
    }
    
}

/**
 *  当扫描到一个元素的结尾时候调用
 */
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
    NSLog(@"结束处理元素:%@", elementName);
    if ([elementName isEqualToString:@"book"]) {
        
        // 添加模型到模型数组中
        [self.books addObject:book];
        // 重置book
        book = nil;
        
    }else {// 解析的不是<books.../>也不是<book.../>元素
        // 利用KVC方式为当前HXBook对象的属性赋值
        [book setValue:currentString forKey:elementName]; 
 // 重置currentString
        currentString = nil;
    }
}
           

运行后,parser开始解析,打印如下:

iOS开发之XML解析

下面介绍是用基于DOM方式的GDataXML解析XML文件。先根据这篇文章配置好环境。将GDataXMLNode.h和GDataXMLNode.m文件拖进项目中。

代码如下:

- (void)testGDataXML {
    // 获取XML文件路径
    NSString *path = [[NSBundle mainBundle] pathForResource:@"text.xml" ofType:nil];
    NSString *xmlString = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
    // 根据XML文件路径加载XML文件
    GDataXMLDocument *xmlDocu = [[GDataXMLDocument alloc] initWithXMLString:xmlString options:0 error:nil];
    
    // 根据XML文件,获取XML文件中的根元素
    GDataXMLElement *xmlEle = [xmlDocu rootElement];
    
    // 在根据主元素,获取其下面的所有直接子元素
    NSArray *array = [xmlEle children];
    NSLog(@"array.count = %lu", (unsigned long)array.count);
    
    // 遍历所有子元素
    for (int i = 0; i < array.count; i ++) {
        // 获取对应索引的子元素
        GDataXMLElement *element = [array objectAtIndex:i];
        
        // 根据元素判断
        if ([[element name] isEqualToString:@"book"]) {
            
            // 创建模型
            book = [[HXBook alloc] init];
            
            //取出元素中属性值
            NSString *IDString = [[element attributeForName:@"id"] stringValue];
            book.ID = [IDString integerValue];
            
            // 获取"book"下的所有直接子元素
            NSArray *childs = [element children];
            for (int j = 0; j < childs.count; j ++) {
                GDataXMLElement *chilE = [childs objectAtIndex:j];
                if ([[chilE name] isEqualToString:@"title"]) {
                    // 书名
                    NSString *title = [chilE stringValue];
                    book.title = title;
                    
                }else if ([[chilE name] isEqualToString:@"author"]) {
                    // 作者
                    NSString *author = [chilE stringValue];
                    book.author = author;
                    
                }else {
                    // 人物
                    NSString *remark = [chilE stringValue];
                    book.remark = remark;
                }
            }
            [self.books addObject:book];
            book = nil;
        }
    }
    // 转换模型完毕后
    for (HXBook *b in self.books) {
        NSLog(@"书:%@", b.remark);
    }
}
           

运行结果:

iOS开发之XML解析

GDataXML是利用根元素的直接子元素来获取内容的。根元素和子元素是相对的。

两种解析XML的方法就介绍到这里。