IOS中XML解析之libxml2
2016-07-30 10:46
525 查看
转自:http://ytwhw.iteye.com/blog/1750920
如有侵犯,请来信oiken@qq.com
IOS SDK自带的XML解析库 libxml2使用方法如下:
准备工作:
1、Xcode4.3.2,新建测试应用libxmltest。
2、把libxml包添加到项目中去。
3、PROJECT=>Build Setting => Searche Paths=>Header Search Paths:把这个拷贝进去${SDKROOT}/usr/include/libxml2。
4、PROJECT=>Build Setting =>Linking => OTHER_LDFLAGS:把这个拷贝进去-lxml2。
一、使用libxml读XML文件
要读xml,需要使用reader,这里介绍两种方式,一种从文件读取,一种从内存读取。其它就是通过libxml库中提供的两个API来建立reader.请看代码:
1、从文件建立reader
xmlTextReaderPtr reader = xmlNewTextReaderFilename(xmlfile);
2、从内存建立reader
// char* memory, int size
xmlTextReaderPtr reader = xmlReaderForMemory(const char *buffer, int size, const char *URL, const char *encoding, int options);
3、从reader中读数据
建立了reader之后,我们就可以通过reader的辅助函数来实现xml数据的读取。在这里,我讲述的是如何读一个文本方式的XML,并没有使用XML的专有模型。这种方式最原始,也是最容易理解的。
要读一个reader中的数据,使用xmlTextReaderRead来读一个元素,XML中的每一个元素都会经过reader依次读取,我们可以根据需要来检查当前reader位置的元素类型,并取出数据为已所用,当然还要释放由reader分配的数据空间。下面来看一下读的例子:
ret = xmlTextReaderRead(reader);
if (ret == 0) return 0;
if (ret != 1) return -2;
element = xmlTextReaderName(reader);
if (element != NULL)
{
ntype = xmlTextReaderNodeType(reader);
if (strcmp((const char*) element, "param-name") == 0)
{
xmlFree(element);
if (XML_READER_TYPE_ELEMENT == ntype)
{
/*......*/
}
}
}
xmlTextReaderRead需要一个参数,就是我们前面进行的一个文本读取器指针,该函数返回1表示成功读取,0表示到达文件尾。当成功读取时,可能使用xmlTextReaderName读取当前位置的元素数据,并可以通过xmlTextTextReaderNodeType来读取XML元素的类型。
/**
* xmlReaderTypes:
*
* Predefined constants for the different types of nodes.
*/
typedef enum {
XML_READER_TYPE_NONE = 0,
XML_READER_TYPE_ELEMENT = 1,
XML_READER_TYPE_ATTRIBUTE = 2,
XML_READER_TYPE_TEXT = 3,
XML_READER_TYPE_CDATA = 4,
XML_READER_TYPE_ENTITY_REFERENCE = 5,
XML_READER_TYPE_ENTITY = 6,
XML_READER_TYPE_PROCESSING_INSTRUCTION = 7,
XML_READER_TYPE_COMMENT = 8,
XML_READER_TYPE_DOCUMENT = 9,
XML_READER_TYPE_DOCUMENT_TYPE = 10,
XML_READER_TYPE_DOCUMENT_FRAGMENT = 11,
XML_READER_TYPE_NOTATION = 12,
XML_READER_TYPE_WHITESPACE = 13,
XML_READER_TYPE_SIGNIFICANT_WHITESPACE = 14,
XML_READER_TYPE_END_ELEMENT = 15,
XML_READER_TYPE_END_ENTITY = 16,
XML_READER_TYPE_XML_DECLARATION = 17
} xmlReaderTypes;
reader支持如上类型,我们可以根据当前类型来读取数据,因为不现的类型,读取数据的方式不同,比如xmlTextReaderReadString只能读元素(XML_READER_TYPE_ELEMENT)的名称或者文件类型(XML_READER_TYPE_TEXT)的数据。注意一点就是reader是按顺序读取每一个元素,在写代码时,应该不要假定后面一定是什么元素或者特定类型,应该去检测,保证软件的稳定性。
使用xmlTextReaderReadString返回一个元素(xmlChar*类型)时,该区域是由库分配的内存区域,需要使用xmlFree来释放,不然就有内存泄漏。
4、读xml的reader的释放与清理
xmlTextReaderClose(reader);
xmlFreeTextReader(reader);
xmlDictCleanup();
xmlCleanupParser();
xmlMemoryDump();
xmlCleanupCharEncodingHandlers();
有一个xmlTextReaderClose函数,当使用该函数时,要注意顺序,一定要在xmlFreeTextReader之前,不然就会出现错误。
二、例子
Cpp代码
self.nsData(NSData数据类型) = [theRequest responseData];//通过网络(WebService等接口获取的XML数据)
xmlTextReaderPtr reader = xmlReaderForMemory ([self.nsData bytes], [self.nsData length], nil, nil, (XML_PARSE_NOENT|XML_PARSE_NOBLANKS | XML_PARSE_NOCDATA | XML_PARSE_NOERROR | XML_PARSE_NOWARNING)); //创建Reader
if (!reader) {
NSLog(@"Failed to load xmlreader");
}
NSString *currentTagName = nil;
NSString *currentTagValue = nil;
NSString *parentTagName = nil;
bool itemStarted = false;
char* temp;
while (true) {
if (!xmlTextReaderRead(reader))
break;
int type = xmlTextReaderNodeType(reader);
switch (type) {
case XML_READER_TYPE_END_ELEMENT:
temp = (char*)xmlTextReaderConstName(reader);
currentTagName = [NSString stringWithCString:temp
encoding:NSUTF8StringEncoding];
if ([currentTagName isEqualToString:@"userInfo"]) {
itemStarted = false;
[self operateCompUser:compUser];//处理解析的数据
[compUser release];
compUser = [[CompUser alloc]init];
}
else if ([currentTagName isEqualToString:@"groupInfo"]) {
itemStarted = false;
[self operateCompDept:compDept]; //处理解析的数据
[compDept release];
compDept = [[CompDept alloc]init];
}
continue;
case XML_READER_TYPE_ELEMENT:
temp = (char*)xmlTextReaderConstName(reader);
currentTagName = [NSString stringWithCString:temp
encoding:NSUTF8StringEncoding];
if ([currentTagName isEqualToString:@"userInfo"]||[currentTagName isEqualToString:@"groupInfo"]) {
parentTagName = currentTagName;
itemStarted = true;
}
continue;
case XML_READER_TYPE_TEXT:
if(itemStarted == false)
continue;
temp = (char*)xmlTextReaderConstValue(reader);
currentTagValue = [NSString stringWithCString:temp
encoding:NSUTF8StringEncoding];
if ([parentTagName isEqualToString:@"userInfo"]) {
if ([currentTagName isEqualToString:@"operateType"]) {
compUser.operateType=currentTagValue;
}
else if ([currentTagName isEqualToString:@"uid"]) {
compUser.uId=currentTagValue;
}
else if ([currentTagName isEqualToString:@"cn"]) {
compUser.cn=currentTagValue;
}
else if ([currentTagName isEqualToString:@"mobile"]) {
compUser.mobile=currentTagValue;
}
else if ([currentTagName isEqualToString:@"telephoneNumber"]) {
compUser.telephoneNumber=currentTagValue;
}
else if ([currentTagName isEqualToString:@"departmentNumber"]) {
compUser.departmentNumber=currentTagValue;
}
else if ([currentTagName isEqualToString:@"deptName"]) {
compUser.deptName=currentTagValue;
}
else if ([currentTagName isEqualToString:@"coName"]) {
compUser.coName=currentTagValue;
}
else if ([currentTagName isEqualToString:@"coNo"]) {
compUser.coNo=currentTagValue;
}
else if ([currentTagName isEqualToString:@"cuOrder"]) {
compUser.cuOrder=currentTagValue;
}
else if ([currentTagName isEqualToString:@"cuMail"]) {
compUser.cuMail=currentTagValue;
}
else if ([currentTagName isEqualToString:@"cuAllShow"]) {
compUser.cuAllShow=currentTagValue;
}
}
if ([parentTagName isEqualToString:@"groupInfo"]) {
if ([currentTagName isEqualToString:@"operateType"]) {
compDept.operateType=currentTagValue;
}
else if ([currentTagName isEqualToString:@"ou"]) {
compDept.ou=currentTagValue;
}
else if ([currentTagName isEqualToString:@"name"]) {
compDept.name=currentTagValue;
}
else if ([currentTagName isEqualToString:@"upId"]) {
compDept.upId=currentTagValue;
}
else if ([currentTagName isEqualToString:@"cuCompanyNumber"]) {
compDept.cuCompanyNumber=currentTagValue;
}
else if ([currentTagName isEqualToString:@"cuAllShow"]) {
compDept.cuAllShow=currentTagValue;
}
else if ([currentTagName isEqualToString:@"cuOrder"]) {
compDept.cuOrder=currentTagValue;
}
}
//self.nsCompData(NSData) = [currentTagValue dataUsingEncoding:NSUTF8StringEncoding];
currentTagValue = nil;
currentTagName = nil;
continue;
case XML_READER_TYPE_ATTRIBUTE:
default:
continue;
}
}
reader = nil;
}
XML数据格式如下:
Xml代码
<?xml version="1.0" encoding="UTF-8"?>
<info>
<userTotal>37</userTotal>
<groupInfo>
<operateType>add</operateType>
<ou>33491028635</ou>
<name>XXX</name>
<upId>XXXX</upId>
<cuCompanyNumber>XXXX</cuCompanyNumber>
<cuAllShow>TRUE</cuAllShow>
<cuOrder>999</cuOrder>
</groupInfo>
<userInfo>
<operateType>add</operateType>
<uid>sd-shen</uid>
<cn>某某某</cn>
<departmentNumber>33491055</departmentNumber>
<deptName>XXXXX</deptName>
<coNo>33491</coNo>
<coName>XXXXXXX</coName>
<cuOrder>999</cuOrder>
<mobile>15655552211</mobile>
<cuMail>XXX@XXX.cn</cuMail>
<cuAllShow>TRUE</cuAllShow>
</userInfo>
</info>
如有侵犯,请来信oiken@qq.com
IOS SDK自带的XML解析库 libxml2使用方法如下:
准备工作:
1、Xcode4.3.2,新建测试应用libxmltest。
2、把libxml包添加到项目中去。
3、PROJECT=>Build Setting => Searche Paths=>Header Search Paths:把这个拷贝进去${SDKROOT}/usr/include/libxml2。
4、PROJECT=>Build Setting =>Linking => OTHER_LDFLAGS:把这个拷贝进去-lxml2。
一、使用libxml读XML文件
要读xml,需要使用reader,这里介绍两种方式,一种从文件读取,一种从内存读取。其它就是通过libxml库中提供的两个API来建立reader.请看代码:
1、从文件建立reader
xmlTextReaderPtr reader = xmlNewTextReaderFilename(xmlfile);
2、从内存建立reader
// char* memory, int size
xmlTextReaderPtr reader = xmlReaderForMemory(const char *buffer, int size, const char *URL, const char *encoding, int options);
3、从reader中读数据
建立了reader之后,我们就可以通过reader的辅助函数来实现xml数据的读取。在这里,我讲述的是如何读一个文本方式的XML,并没有使用XML的专有模型。这种方式最原始,也是最容易理解的。
要读一个reader中的数据,使用xmlTextReaderRead来读一个元素,XML中的每一个元素都会经过reader依次读取,我们可以根据需要来检查当前reader位置的元素类型,并取出数据为已所用,当然还要释放由reader分配的数据空间。下面来看一下读的例子:
ret = xmlTextReaderRead(reader);
if (ret == 0) return 0;
if (ret != 1) return -2;
element = xmlTextReaderName(reader);
if (element != NULL)
{
ntype = xmlTextReaderNodeType(reader);
if (strcmp((const char*) element, "param-name") == 0)
{
xmlFree(element);
if (XML_READER_TYPE_ELEMENT == ntype)
{
/*......*/
}
}
}
xmlTextReaderRead需要一个参数,就是我们前面进行的一个文本读取器指针,该函数返回1表示成功读取,0表示到达文件尾。当成功读取时,可能使用xmlTextReaderName读取当前位置的元素数据,并可以通过xmlTextTextReaderNodeType来读取XML元素的类型。
/**
* xmlReaderTypes:
*
* Predefined constants for the different types of nodes.
*/
typedef enum {
XML_READER_TYPE_NONE = 0,
XML_READER_TYPE_ELEMENT = 1,
XML_READER_TYPE_ATTRIBUTE = 2,
XML_READER_TYPE_TEXT = 3,
XML_READER_TYPE_CDATA = 4,
XML_READER_TYPE_ENTITY_REFERENCE = 5,
XML_READER_TYPE_ENTITY = 6,
XML_READER_TYPE_PROCESSING_INSTRUCTION = 7,
XML_READER_TYPE_COMMENT = 8,
XML_READER_TYPE_DOCUMENT = 9,
XML_READER_TYPE_DOCUMENT_TYPE = 10,
XML_READER_TYPE_DOCUMENT_FRAGMENT = 11,
XML_READER_TYPE_NOTATION = 12,
XML_READER_TYPE_WHITESPACE = 13,
XML_READER_TYPE_SIGNIFICANT_WHITESPACE = 14,
XML_READER_TYPE_END_ELEMENT = 15,
XML_READER_TYPE_END_ENTITY = 16,
XML_READER_TYPE_XML_DECLARATION = 17
} xmlReaderTypes;
reader支持如上类型,我们可以根据当前类型来读取数据,因为不现的类型,读取数据的方式不同,比如xmlTextReaderReadString只能读元素(XML_READER_TYPE_ELEMENT)的名称或者文件类型(XML_READER_TYPE_TEXT)的数据。注意一点就是reader是按顺序读取每一个元素,在写代码时,应该不要假定后面一定是什么元素或者特定类型,应该去检测,保证软件的稳定性。
使用xmlTextReaderReadString返回一个元素(xmlChar*类型)时,该区域是由库分配的内存区域,需要使用xmlFree来释放,不然就有内存泄漏。
4、读xml的reader的释放与清理
xmlTextReaderClose(reader);
xmlFreeTextReader(reader);
xmlDictCleanup();
xmlCleanupParser();
xmlMemoryDump();
xmlCleanupCharEncodingHandlers();
有一个xmlTextReaderClose函数,当使用该函数时,要注意顺序,一定要在xmlFreeTextReader之前,不然就会出现错误。
二、例子
Cpp代码
self.nsData(NSData数据类型) = [theRequest responseData];//通过网络(WebService等接口获取的XML数据)
xmlTextReaderPtr reader = xmlReaderForMemory ([self.nsData bytes], [self.nsData length], nil, nil, (XML_PARSE_NOENT|XML_PARSE_NOBLANKS | XML_PARSE_NOCDATA | XML_PARSE_NOERROR | XML_PARSE_NOWARNING)); //创建Reader
if (!reader) {
NSLog(@"Failed to load xmlreader");
}
NSString *currentTagName = nil;
NSString *currentTagValue = nil;
NSString *parentTagName = nil;
bool itemStarted = false;
char* temp;
while (true) {
if (!xmlTextReaderRead(reader))
break;
int type = xmlTextReaderNodeType(reader);
switch (type) {
case XML_READER_TYPE_END_ELEMENT:
temp = (char*)xmlTextReaderConstName(reader);
currentTagName = [NSString stringWithCString:temp
encoding:NSUTF8StringEncoding];
if ([currentTagName isEqualToString:@"userInfo"]) {
itemStarted = false;
[self operateCompUser:compUser];//处理解析的数据
[compUser release];
compUser = [[CompUser alloc]init];
}
else if ([currentTagName isEqualToString:@"groupInfo"]) {
itemStarted = false;
[self operateCompDept:compDept]; //处理解析的数据
[compDept release];
compDept = [[CompDept alloc]init];
}
continue;
case XML_READER_TYPE_ELEMENT:
temp = (char*)xmlTextReaderConstName(reader);
currentTagName = [NSString stringWithCString:temp
encoding:NSUTF8StringEncoding];
if ([currentTagName isEqualToString:@"userInfo"]||[currentTagName isEqualToString:@"groupInfo"]) {
parentTagName = currentTagName;
itemStarted = true;
}
continue;
case XML_READER_TYPE_TEXT:
if(itemStarted == false)
continue;
temp = (char*)xmlTextReaderConstValue(reader);
currentTagValue = [NSString stringWithCString:temp
encoding:NSUTF8StringEncoding];
if ([parentTagName isEqualToString:@"userInfo"]) {
if ([currentTagName isEqualToString:@"operateType"]) {
compUser.operateType=currentTagValue;
}
else if ([currentTagName isEqualToString:@"uid"]) {
compUser.uId=currentTagValue;
}
else if ([currentTagName isEqualToString:@"cn"]) {
compUser.cn=currentTagValue;
}
else if ([currentTagName isEqualToString:@"mobile"]) {
compUser.mobile=currentTagValue;
}
else if ([currentTagName isEqualToString:@"telephoneNumber"]) {
compUser.telephoneNumber=currentTagValue;
}
else if ([currentTagName isEqualToString:@"departmentNumber"]) {
compUser.departmentNumber=currentTagValue;
}
else if ([currentTagName isEqualToString:@"deptName"]) {
compUser.deptName=currentTagValue;
}
else if ([currentTagName isEqualToString:@"coName"]) {
compUser.coName=currentTagValue;
}
else if ([currentTagName isEqualToString:@"coNo"]) {
compUser.coNo=currentTagValue;
}
else if ([currentTagName isEqualToString:@"cuOrder"]) {
compUser.cuOrder=currentTagValue;
}
else if ([currentTagName isEqualToString:@"cuMail"]) {
compUser.cuMail=currentTagValue;
}
else if ([currentTagName isEqualToString:@"cuAllShow"]) {
compUser.cuAllShow=currentTagValue;
}
}
if ([parentTagName isEqualToString:@"groupInfo"]) {
if ([currentTagName isEqualToString:@"operateType"]) {
compDept.operateType=currentTagValue;
}
else if ([currentTagName isEqualToString:@"ou"]) {
compDept.ou=currentTagValue;
}
else if ([currentTagName isEqualToString:@"name"]) {
compDept.name=currentTagValue;
}
else if ([currentTagName isEqualToString:@"upId"]) {
compDept.upId=currentTagValue;
}
else if ([currentTagName isEqualToString:@"cuCompanyNumber"]) {
compDept.cuCompanyNumber=currentTagValue;
}
else if ([currentTagName isEqualToString:@"cuAllShow"]) {
compDept.cuAllShow=currentTagValue;
}
else if ([currentTagName isEqualToString:@"cuOrder"]) {
compDept.cuOrder=currentTagValue;
}
}
//self.nsCompData(NSData) = [currentTagValue dataUsingEncoding:NSUTF8StringEncoding];
currentTagValue = nil;
currentTagName = nil;
continue;
case XML_READER_TYPE_ATTRIBUTE:
default:
continue;
}
}
reader = nil;
}
XML数据格式如下:
Xml代码
<?xml version="1.0" encoding="UTF-8"?>
<info>
<userTotal>37</userTotal>
<groupInfo>
<operateType>add</operateType>
<ou>33491028635</ou>
<name>XXX</name>
<upId>XXXX</upId>
<cuCompanyNumber>XXXX</cuCompanyNumber>
<cuAllShow>TRUE</cuAllShow>
<cuOrder>999</cuOrder>
</groupInfo>
<userInfo>
<operateType>add</operateType>
<uid>sd-shen</uid>
<cn>某某某</cn>
<departmentNumber>33491055</departmentNumber>
<deptName>XXXXX</deptName>
<coNo>33491</coNo>
<coName>XXXXXXX</coName>
<cuOrder>999</cuOrder>
<mobile>15655552211</mobile>
<cuMail>XXX@XXX.cn</cuMail>
<cuAllShow>TRUE</cuAllShow>
</userInfo>
</info>
相关文章推荐
- iOS开发之功能模块--Apns推送中的的json格式介绍
- iOS 多线程纪录
- 一段简单的代码,实现iOS源生播放器,在线播放视频
- iOS 第三方框架- AFNetworking的基本使用
- IOS树视图学习总结
- iOS使用fmdb创建单例
- 视图动画效果
- IOS 随记
- IOS 汤姆猫核心代码
- IOS 随笔记录
- iOS 音视频: 编译 FFmpeg-3.1.1
- iOS线程和进程的区别和联系
- iPhone实现XML的POST传递并接收数据
- 玩转iOS开发:使用AVFoundation实现扫码
- iOS获取当前屏幕控制器的方法
- iOS核心动画笔记1-图层的树状结构
- iOS核心动画笔记2-寄宿图
- iOS--Segment的简单定制
- iOS-截屏,从相册选择图片,制作磨砂效果图片
- iOS开源照片浏览器框架SGPhotoBrowser的设计与实现