NSXMLParser读取XML文件并将数据显示到TableView上

关于XML,有两种解析方式,分别是SAX(Simple API for XML,基于事件驱动的解析方式,逐行解析数据,采用协议回调机制)和DOM(Document Object Model ,文档对象模型。解析时需要将XML文件整体读入,并且将XML结构化成树状,使用时再通过树状结构读取相关数据,查找特定节点,然后对节点进行读或写)。苹果官方原生的NSXMLParse类库采用第一种方式,即SAX方式解析XML,它基于事件通知的模式,一边读取文档一边解析数据,不用等待文档全部读入以后再解析,所以如果你正打印解析的数据,而解析过程中间出现了错误,那么在错误节点之间的数据会正常打印,错误后面的数据不会被打印。解析过程由NSXMLParserDelegate协议方法回调。

首先先创建一个xml文件就叫做xml.xml吧:

<?xml version="1.0" encoding="UTF-8"?>
<Root>
    <Student>
        <pid>1</pid>
        <name>Jack</name>
        <sex>Male</sex>
        <age>18</age>
    </Student>
    <Student>
        <pid>2</pid>
        <name>Jodan</name>
        <sex>Male</sex>
        <age>19</age>
    </Student>
    <Student>
        <pid>3</pid>
        <name>Mily</name>
        <sex>Female</sex>
        <age>18</age>
    </Student>
    <Student>
        <pid>4</pid>
        <name>Rena</name>
        <sex>Female</sex>
        <age>20</age>
    </Student>
    <Student>
        <pid>5</pid>
        <name>Amy</name>
        <sex>Female</sex>
        <age>22</age>
    </Student>
    <Student>
        <pid>6</pid>
        <name>Teresa</name>
        <sex>Female</sex>
        <age>20</age>
    </Student>
</Root>

 接首创建一个相对应的M

//Person.h
#import <Foundation/Foundation.h>

@interface Person : NSObject

@property (nonatomic,copy) NSString *pid;
@property (nonatomic,copy) NSString *name;
@property (nonatomic,copy) NSString *sex;
@property (nonatomic,copy) NSString *age;

@end

//Person.m
#import "Person.h"

@implementation Person

@synthesize pid,name,age,sex;
@end

接着添加一个自定义UITableViewCell类就让它叫做CustomTableViewCell.m吧,下一步将用到,代码如下:

//CustomTableViewCell.h
#import <UIKit/UIKit.h>

@interface CustomTableViewCell : UITableViewCell

@property UILabel *lblName;
@property UILabel *lblSex;
@property UILabel *lblAge;


@end


//CustomTableViewCell.m
#import "CustomTableViewCell.h"

@implementation CustomTableViewCell

@synthesize lblAge,lblName,lblSex;

- (void)awakeFromNib {
    // Initialization code
}

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        UILabel *titleOfNameLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 10, 60, 20)];
        titleOfNameLabel.text = @"姓名:";
        UILabel *titleOfAgeLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 40, 60, 20)];
        titleOfAgeLabel.text = @"年龄:";
        
        UILabel *titleOfSexLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 70, 60, 20)];
        titleOfSexLabel.text = @"性别:";
        
        //titleOfNameLabel.backgroundColor = [UIColor blackColor];
        
        [self addSubview:titleOfNameLabel];
        [self addSubview:titleOfAgeLabel];
        [self addSubview:titleOfSexLabel];
        
        lblName = [[UILabel alloc] initWithFrame:CGRectMake(80, 10, 100, 20)];
        lblAge = [[UILabel alloc] initWithFrame:CGRectMake(80, 40, 100, 20)];
        lblSex = [[UILabel alloc] initWithFrame:CGRectMake(80, 70, 100, 20)];
        
        [self addSubview:lblName];
        [self addSubview:lblAge];
        [self addSubview:lblSex];
    }
    return self;
}

- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
    [super setSelected:selected animated:animated];

    // Configure the view for the selected state
}

@end

在storyboard内添加一个ViewController并加一个TableView并设置好相应的约束条件后添加一个继承自UIViewController的类估且就叫做XmlToTableViewController,并设置上一步在storyboard添加的ViewController的Customer Class为XmlToTableViewController。 

XmlToTableViewController要实现NSXMLParserDelegate这个接口,并选择相应要实现的方法。

  1 //XmlToTableViewController.h
  2 #import "ViewController.h"
  3 #import "Person.h"
  4 
  5 @interface XmlToTableViewController : ViewController
  6 
  7 @property (weak, nonatomic) IBOutlet UITableView *tableView;
  8 
  9 @property (nonatomic,strong) NSXMLParser *parser;
 10 @property (nonatomic,strong) NSMutableArray *personArray;
 11 @property (nonatomic,copy) NSString *currentElement;
 12 @property (nonatomic,strong) Person *person;
 13 
 14 @end
 15 
 16 
 17 //XmlToTableViewController.m
 18 #import "XmlToTableViewController.h"
 19 #import "CustomTableViewCell.h"
 20 
 21 @interface XmlToTableViewController () <UITableViewDataSource,UITableViewDelegate,NSXMLParserDelegate>
 22 
 23 @end
 24 
 25 @implementation XmlToTableViewController
 26 
 27 - (void)viewDidLoad {
 28     [super viewDidLoad];
 29     
 30     dispatch_queue_t q1 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
 31     
 32     dispatch_async(q1, ^{
 33         
 34 
 35     });
 36     
 37     NSBundle *bundle = [NSBundle mainBundle];
 38     NSString *path = [bundle pathForResource:@"xml" ofType:@"xml"];
 39     NSData *data = [NSData dataWithContentsOfFile:path];
 40     self.parser = [[NSXMLParser alloc] initWithData:data];
 41     //添加代理
 42     self.parser.delegate = self;
 43     self.personArray = [NSMutableArray arrayWithCapacity:5];
 44     [self.parser parse];
 45     
 46     self.tableView.delegate = self;
 47     self.tableView.dataSource = self;
 48 }
 49 
 50 
 51 
 52 //几个代理方法的实现,是按逻辑上的顺序排列的,但实际调用过程中中间三个可能因为循环等问题乱掉顺序
 53 //开始解析
 54 - (void)parserDidStartDocument:(NSXMLParser *)parser {
 55     NSLog(@"parserDidStartDocument");
 56 }
 57 
 58 -(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary<NSString *,NSString *> *)attributeDict {
 59     self.currentElement = elementName;
 60     if([self.currentElement isEqualToString:@"Student"]) {
 61         self.person = [[Person alloc] init];
 62     }
 63 }
 64 
 65 //获取节点内容
 66 -(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
 67     if ([self.currentElement isEqualToString:@"pid"]) {
 68         [self.person setPid:string];
 69     } else if([self.currentElement isEqualToString:@"name"]) {
 70         [self.person setName:string];
 71     } else if([self.currentElement isEqualToString:@"sex"]) {
 72         [self.person setSex:string];
 73     } else if([self.currentElement isEqualToString:@"age"]) {
 74         [self.person setAge:string];
 75     }
 76 }
 77 
 78 //当一个节点读取完成后
 79 -(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
 80     if([elementName isEqualToString:@"Student"]) {
 81         [self.personArray addObject:self.person];
 82     }
 83     self.currentElement = nil;
 84 }
 85 
 86 //完成XML文件的读取
 87 -(void)parserDidEndDocument:(NSXMLParser *)parser {
 88     NSLog(@"parserDidEndDocument");
 89     NSLog(@"Student's count is %lu",(unsigned long)[self.personArray count]);
 90     [self.tableView reloadData];
 91 }
 92 
 93 
 94 //MARK:TABLEVIEW
 95 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
 96     return [self.personArray count];
 97 }
 98 
 99 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
100     NSString *idenfifier = @"Cell";
101     //PersoUITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:idenfifier];
102     CustomTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:idenfifier];
103     if (cell == nil) {
104         //用xib文件先画好
105         /*cell = [[[NSBundle mainBundle] loadNibNamed:@"PersonUITableViewCell" owner:nil options:nil] firstObject];
106         Person *currentPerson = [self.personArray objectAtIndex:indexPath.row];
107         if (currentPerson) {
108             cell.lblName.text = currentPerson.name;
109             cell.lblAge.text = currentPerson.age;
110             cell.lblId.text = currentPerson.pid;
111             cell.lblSex.text = currentPerson.sex;
112         }*/
113         
114         cell = [[CustomTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:idenfifier];
115         
116         [tableView registerClass:[CustomTableViewCell class] forCellReuseIdentifier:idenfifier];
117     }
118     Person *currentPerson = [self.personArray objectAtIndex:indexPath.row];
119     if (currentPerson) {
120         cell.lblName.text = currentPerson.name;
121         cell.lblAge.text = currentPerson.age;
122         cell.lblSex.text = currentPerson.sex;
123     }
124 
125     return cell;
126 }
127 
128 - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
129     return 126;
130 }

 最终的效果:

原文地址:https://www.cnblogs.com/foxting/p/5596561.html