- 浏览: 13630031 次
- 性别:
- 来自: 洛杉矶
文章分类
- 全部博客 (1994)
- Php / Pear / Mysql / Node.js (378)
- Javascript /Jquery / Bootstrap / Web (435)
- Phone / IOS / Objective-C / Swift (137)
- Ubuntu / Mac / Github / Aptana / Nginx / Shell / Linux (335)
- Perl / Koha / Ruby / Markdown (8)
- Java / Jsp (12)
- Python 2 / Wxpython (25)
- Codeigniter / CakePHP (32)
- Div / Css / XML / HTML5 (179)
- WP / Joomla! / Magento / Shopify / Drupal / Moodle / Zimbra (275)
- Apache / VPN / Software (31)
- AS3.0/2.0 / Flex / Flash (45)
- Smarty (6)
- SEO (24)
- Google / Facebook / Pinterest / SNS (80)
- Tools (22)
最新评论
-
1455975567:
xuezhongyu01 写道wocan23 写道我想问下那个 ...
Mysql: LBS实现查找附近的人 (两经纬度之间的距离) -
xuezhongyu01:
wocan23 写道我想问下那个111.1是怎么得来的我也看不 ...
Mysql: LBS实现查找附近的人 (两经纬度之间的距离) -
18335864773:
试试 pageoffice 在线打开 PDF 文件吧. pag ...
jquery在线预览PDF文件,打开PDF文件 -
青春依旧:
opacity: 0.5; 个人喜欢这种方式!关于其他css特 ...
css透明度的设置 (兼容所有浏览器) -
July01:
推荐用StratoIO打印控件,浏览器和系统的兼容性都很好,而 ...
搞定网页打印自动分页问题
关联:iOS中XML解析 (一) TBXML (实例:打印xml内容及存储到数组)
关于libxml库的基本使用,在http://xmlsoft.org/网上有文档。
准备工作:
- project=>Edit project setting =>Build=> Searche Paths=>Header Search Paths:把这个拷贝进去${SDKROOT}/usr/include/libxml2,网上有很多都是没给这个的${SDKROOT}。
- linking => other linker flags =>-lxml2拷贝进去
- 把dylib包添加导项目中去。
- 编译 如果还有问题,nclean all targets 确保 两项都打钩 并且 empty xcode 的cache
一、使用libxml读XML文件
要读xml,需要使用reader,这里介绍两种方式,一种从文件读取,一种从内存读取。其它就是通过libxml库中提供的两个API来建立reader.请看代码:
1、从文件建立reader
xmlTextReaderPtr reader = xmlNewTextReaderFilename(xmlfile);
2、从内存建立reader
// char* memory, int size xmlTextReaderPtr reader = xmlReaderForMemory(memory, size, NULL, "UTF-8", 0);
从上述代码来看,建立一个reader是非常容易的。
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之前,不然就会出现错误。
二、实例
1. 假设xml地址为 http://cdn.domain.com/ipad/settings/config.xml 格式为:
<?xml version="1.0"?> <settings> <popupAd> <show>1</show> <count>3</count> </popupAd> </settings>
读取:
.h
#import <Foundation/Foundation.h> #include <libxml/xmlreader.h> @interface NewsFeedParser : NSObject { } @end
.m
-(void)readXml { NSURLResponse *response; NSError *error; NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://cdn.domain.com/ipad/settings/config.xml"]]; NSData *settingData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error]; xmlTextReaderPtr reader = xmlReaderForMemory([settingData bytes], [settingData length], nil, nil, (XML_PARSE_NOENT|XML_PARSE_NOBLANKS | XML_PARSE_NOCDATA | XML_PARSE_NOERROR | XML_PARSE_NOWARNING)); if(!reader) NSLog(@"Failed to load setting config xml !"); else { char *temp; NSString *currentTagName = nil; NSString *currentTagValue = nil; NSMutableDictionary *config = [NSMutableDictionary dictionary]; while (TRUE) { if(!xmlTextReaderRead(reader)) break; //NSLog(@"========> %s",xmlTextReaderName(reader)); if(xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT) { temp = (char *)xmlTextReaderConstName(reader); currentTagName = [NSString stringWithCString:temp encoding:NSUTF8StringEncoding]; if([currentTagName isEqualToString:@"show"] || [currentTagName isEqualToString:@"count"]) { temp = (char *)xmlTextReaderReadString(reader); currentTagValue = [NSString stringWithCString:temp encoding:NSUTF8StringEncoding]; //NSLog(@"===> TagName: %@",currentTagName); //NSLog(@"===> TagValue: %@",currentTagValue); [config setObject:currentTagValue forKey:currentTagName]; currentTagValue = nil; } } } NSLog(@"======> %@",[config objectForKey:@"show"]); NSLog(@"======> %@",[config objectForKey:@"count"]); } }
2. 假设xml地址为 http://www.domain.com/feed/ipad/marketchart/main.rss 格式为:
<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/"> <channel> <atom:link href="http://www.domain.com/feed/ipad/marketchart/main.rss" rel="self" type="application/rss+xml" /> <title><![CDATA[domain.com : Market data]]></title> <description><![CDATA[Market data RSS Feed ]]></description> <link>http://www.domain.com/feed/ipad/marketchart/main.rss</link> <copyright>All articles are copyrighted by IBTimes.com</copyright> <image> <url>http://img.domain.com/www/site/2010/main/images/heading_editores_pick_logo.png</url> <title><![CDATA[domain.com : Market data]]></title> <link>http://www.domain.com/feed/ipad/marketchart/main.rss</link> </image> <item> <title><![CDATA[DOW]]></title> <last>13085.53</last> <symbol>^DJI</symbol> <change>-114.02</change> <description><![CDATA[ description ]]></description> <pubDate>Wed, 04 Apr 2012 14:51:00 EDT</pubDate> </item> <item> <title><![CDATA[NYSE]]></title> <last>8151.97</last> <symbol>$NYA</symbol> <change>0</change> <description><![CDATA[ description ]]></description> <pubDate>Fri, 24 Feb 2012 17:05:00 EST</pubDate> </item> <item> <title><![CDATA[NASDAQ]]></title> <last>3063.63</last> <symbol>$COMP</symbol> <change>-49.94</change> <description><![CDATA[ description ]]></description> <pubDate>Wed, 04 Apr 2012 14:45:00 EDT</pubDate> </item> <item> <title><![CDATA[S&P 500]]></title> <last>1399.64</last> <symbol>$SPX</symbol> <change>-13.74</change> <description><![CDATA[ description ]]></description> <pubDate>Wed, 04 Apr 2012 14:45:00 EDT</pubDate> </item> </channel> </rss>
以item为单位的循环
NewsFeedParser.h
#import <Foundation/Foundation.h> #include <libxml/xmlreader.h> @interface NewsFeedParser : NSObject { } +(NSMutableArray*) parseFeedFromUrl:(NSString *) url; @end
NewsFeedParser.m
#import "NewsFeedParser.h" @implementation NewsFeedParser +(NSMutableArray*) parseFeedFromUrl:(NSString *) url { NSMutableArray *itemsArray = [NSMutableArray array]; //NSLog(@"NewsFeedParser:%@ begin\n", url); NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:url]]; NSURLResponse *response; NSError *error; NSData *xmlData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error]; xmlTextReaderPtr reader = xmlReaderForMemory([xmlData bytes], [xmlData length], nil, nil, (XML_PARSE_NOENT|XML_PARSE_NOBLANKS | XML_PARSE_NOCDATA | XML_PARSE_NOERROR | XML_PARSE_NOWARNING)); if (!reader) { NSLog(@"Failed to load xmlreader"); return itemsArray; } NSString *currentTagName = nil; NSDictionary *currentItem = nil; NSString *currentTagValue = nil; bool itemStarted = false; bool authorStarted = false; bool categoryStarted = 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:@"item"]) { itemStarted = false; } continue; case XML_READER_TYPE_ELEMENT: //We are starting an element temp = (char*)xmlTextReaderConstName(reader); currentTagName = [NSString stringWithCString:temp encoding:NSUTF8StringEncoding]; if ([currentTagName isEqualToString:@"item"]) { //NSLog(@"Item begin\n"); currentItem = [NSMutableDictionary dictionary]; [itemsArray addObject:currentItem]; itemStarted = true; authorStarted = false; categoryStarted = false; } if([currentTagName isEqualToString:@"author"]){ authorStarted = true; categoryStarted = false; } if([currentTagName isEqualToString:@"category"]){ categoryStarted = true; authorStarted = false; } if(itemStarted == true && [currentTagName isEqualToString:@"media:content"]) { temp = (char*)xmlTextReaderGetAttribute(reader,"url"); currentTagValue = [NSString stringWithCString:temp encoding:NSUTF8StringEncoding]; [currentItem setValue:currentTagValue forKey:currentTagName]; //NSLog(@"%@ - %@\n", currentTagName, currentTagValue); currentTagValue = nil; } continue; case XML_READER_TYPE_TEXT: //The current tag has a text value, stick it into the current person if(itemStarted == false) continue; temp = (char*)xmlTextReaderConstValue(reader); currentTagValue = [NSString stringWithCString:temp encoding:NSUTF8StringEncoding]; //NSLog(@"%@ - %@\n", currentTagName, currentTagValue); if([currentTagName isEqualToString:@"name"]){ if(authorStarted) [currentItem setValue:currentTagValue forKey:@"author"]; if(categoryStarted) [currentItem setValue:currentTagValue forKey:@"category"]; } else{ [currentItem setValue:currentTagValue forKey:currentTagName]; } currentTagValue = nil; currentTagName = nil; continue; case XML_READER_TYPE_ATTRIBUTE: //temp = (char*)xmlTextReaderConstValue(reader); //NSLog(@"%s\n", temp); default: continue; } } //NSLog(@"NewsFeedParser:%@ done\n", url); return itemsArray; } @end
ViewController.m
#import "NewsFeedParser.h" -(void) loadMarketData{ dispatch_async(dispatch_get_global_queue(0, 0), ^{ NSMutableArray *items = [NewsFeedParser parseFeedFromUrl:@"http://www.domain.com/feed/ipad/marketchart/main.rss"]; if([items count] == 0) return; NSLog(@"Title => %@", [[items objectAtIndex:0] objectForKey:@"title"]); NSLog(@"Last=> %@", [[items objectAtIndex:0] objectForKey:@"last"]); NSLog(@"Change=> %@", [[items objectAtIndex:0] objectForKey:@"change"]); }); }
其他一些方法:
libxml库提供了一些.net风格的函数,以流的形式来读取并分析xml文件.
<libxml/xmlreader.h> xmlTextReader xmlTextReaderPtr //XmlReader的结构体及其指针 xmlTextReaderPtr xmlReaderForFile (const char * filename, const char * encoding, int options) //打开一个xml文件并返回xmlreader对象,准备开始分析. int xmlTextReaderRead (xmlTextReaderPtr reader) //读取下一个节点(注意,是下一个,不是下一个同层节点) int xmlTextReaderNext (xmlTextReaderPtr reader) //读取下一个同层节点 int xmlTextReaderNodeType (xmlTextReaderPtr reader) //判断当前节点的类型 xmlChar *xmlTextReaderGetAttribute (xmlTextReaderPtr reader, const xmlChar * name) //获取当前节点的指定属性 xmlChar *xmlTextReaderReadString (xmlTextReaderPtr reader) //读取当前节点下的text xmlNodePtr xmlTextReaderExpand (xmlTextReaderPtr reader) //将当前节点展开成一个节点对象(慎用) int xmlTextReaderHasValue (xmlTextReaderPtr reader) //判断当前节点是否有text值 int xmlTextReaderHasAttributes (xmlTextReaderPtr reader) //判断当前节点是否包含属性 int xmlTextReaderMoveToAttribute (xmlTextReaderPtr reader, const xmlChar * name) //移动指针到当前节点的指定属性名的属性 int xmlTextReaderMoveToAttributeNo (xmlTextReaderPtr reader, int no) //移动指针到当前节点指定属性编号的属性 int xmlTextReaderMoveToElement (xmlTextReaderPtr reader) //将指针移会当前节点 int xmlTextReaderMoveToFirstAttribute (xmlTextReaderPtr reader) //将指针移动到当前节点的第一个属性 int xmlTextReaderMoveToNextAttribute (xmlTextReaderPtr reader) //将指针移动到当前节点的下一个属性 xmlChar *xmlTextReaderName (xmlTextReaderPtr reader) //返回当前节点的名字
libxml自定义了一个字符类型xmlChar,其本质是 unsigned char.
另外,libxml提供了一个宏来将char*转换成xmlChar*, 名字很有趣,叫 BAD_CAST 它的本质其实是 unsigned char*.
为了方便对xmlChar类型字符串的操作,libxml提供了自己的函数,它们的定义于标准c函数库中的字符串函数很像.
xmlChar* xmlStrcat (xmlChar *cur, const xmlChar * add) const xmlChar *xmlStrchr(const xmlChar * str, xmlChar val) int xmlStrcmp (const xmlChar * str1, const xmlChar * str2) int xmlStrlen (const xmlChar * str) xmlChar *xmlStrncat (xmlChar * cur, const xmlChar * add, int len) int xmlStrncmp (const xmlChar * str1, const xmlChar * str2, int len) const xmlChar *xmlStrstr (const xmlChar * str, const xmlChar * val)
更多函数大家可以参考
http://xmlsoft.org/html/libxml-xmlstring.html
关联:iOS中XML解析 (一) TBXML (实例:打印xml内容及存储到数组)
发表评论
-
手机firebug查看网页代码 How to View Website Source Codes on iPad / iPhone
2016-04-26 02:41 1120You’re using your iPad to br ... -
Android模拟器genymotion的安装和使用
2016-03-18 01:16 2470Genymotion概述 Genymotion是一套完整的 ... -
编码之道:取个好名字很重要
2015-10-14 05:19 1116代码就是程序员的孩子,给“孩子”取个好听的名字很重 ... -
Genymotion - 强大好用高性能的 Android 模拟器 (在电脑流畅运行APK安卓软件游戏的利器)
2015-06-05 13:34 7320随着 Android 系统的应用和游戏越来越丰富,甚至有 ... -
收集几个移动平台浏览器的User-Agent
2014-07-23 02:33 2973List of all Mobile Browsers ... -
常用浏览器修改User-Agent的方法
2014-06-28 02:58 10901之前有介绍收集的几个移动平台浏览器的User-Agent,以 ... -
更简洁的方式修改Chrome的User Agent,轻松体验移动版网络
2014-06-28 02:53 6866国庆节在家宅着,使用3g上网卡上网,和在公司上网不一样的是 ... -
3个检测浏览器User-Agent信息的网站
2014-06-28 02:52 2495刚刚在收集各个移动平台浏览器的User-Agent(参见这 ... -
根据移动设备屏幕像素密度,给予不同分辨率的图片
2014-06-26 00:52 2906在出现iphone4之前的相当长的时间内,网站开发人员 ... -
视网膜New iPad与普通分辨率iPad页面的兼容处理
2014-06-26 00:44 1268一、这是篇经验分享 ... -
iOS8开发-Swift编程
2014-06-25 00:45 1825课时列表 章节1:第一个Swift应用 ... -
Swift中文教程(二十三) 高级运算符
2014-06-25 00:43 780除了基本操作符中所讲的运算符,Swift还有许多复杂的高级 ... -
Swift中文教程(二十二) 泛型
2014-06-25 00:35 1003泛型代码可以让你写出根据自我需求定义、适用于任何类型的,灵 ... -
Swift中文教程(二十一) 协议
2014-06-24 05:25 1003Protocol(协议)用于统一方法和属性的名称,而不实现任 ... -
Swift中文教程(二十) 扩展
2014-06-24 00:47 682扩展就是向一个已有的类、结构体或枚举类型添加新功能(fun ... -
Swift中文教程(十九) 类型嵌套
2014-06-24 00:44 883枚举类型常被用于实现特定类或结构体的功能。也能够在有多种变量 ... -
Swift中文教程(十八) 类型检查
2014-06-24 00:41 721类型检查是一种检查类实例的方式,并且或者也是让实例作为它的 ... -
Swift中文教程(十七) 可选链
2014-06-17 05:11 862可选链(Optional Chaining)是一种可以请求 ... -
Swift中文教程(十六) 自动引用计数
2014-06-17 05:05 1241Swift使用自动引用计数(ARC)来管理应用程序的内存使 ... -
Swift中文教程(十五) 析构
2014-06-17 04:57 995在一个类的实例被释放之前,析构函数会被调用。用关键字dei ...
相关推荐
libxml2-2.7.4,能够解析并生成xml格式的文件
利用libxml2生成,解析,修改xml文件示例,安装libxml2库, sudo apt-get install libxml2-dev。使用libxml2库进行xml文件的操作,取出了平台差异化,便于在不同的平台都可以进行文件的操作,不受平台系统的限制,...
Ubuntu下C语言使用libxml2库创建、解析xml文件,包括对节点的增、删、改、查等
libxml2是开源的跨平台XML解析器,用C语言实现。源代码可从http://xmlsoft.org/downloads.html获取,本资源提供的是在win32/vc6/x86,win32/gcc/x86,aix5.3/gcc/powerpc,macosx10.5/gcc/x86,rhel5/gcc/x86,...
开源跨平台XML解析器-LIBXML2,V2.7.8,以及WIN32下的VC6和codeblocks工程文件
很详细的libxml实例详解参考,c语言解析xml文件不错的学习文档
官方离线安装包,亲测可用。使用rpm -ivh [rpm完整包名] 进行安装
gtK Cairo LibCurl LibXML 解析实例gtK Cairo LibCurl LibXML 解析实例gtK Cairo LibCurl LibXML 解析实例gtK Cairo LibCurl LibXML 解析实例gtK Cairo LibCurl LibXML 解析实例gtK Cairo LibCurl LibXML 解析实例
libxml2:纯C语言,默认包含在iOS SDK中,同时支持DOM和SAX解析 GDataXML:DOM方式解析,由Google开发,基于libxml2 2-2、苹果原生 NSXMLParser:SAX方式解析,使用简单 2-3、本人基于苹果原生NSXMLParser...
GTK Cairo LibCurl LibXML 解析实例
主要是利用java代码解析xml字符串、生成xml字符串、解析xml文件、生成xml文件。
官方离线安装包,亲测可用
通过调用libxml接口,对xml文件进行生成和解析。
纯C语言解析xml字符串,有实例,保证可用,含makefile xmlparse.c xmlparse.h testxml.c 目录:/export/home/chcard/testxml 日志:/export/home/chcard/log testxml.c 是一个测试用例,包含了常用的方法,并有注解 ...
XML文件的解析--libxml库函数解释
Libxml是一个实现读、创建及操纵XML数据功能的C语言库。这个指南提供例子代码并给出它基本功能的解释。在这个项目的主页上有Libxml及更多关于它可用的资料。包含有完整的API文档。这个指南并不能替代这些完整的文档...
开源跨平台XML解析器-LIBXML2--库-SOLARIS10/SPARC,源代码可从http://xmlsoft.org/downloads.html或资源“开源跨平台XML解析器-LIBXML2--C源代码及VC6工程文件”获取
开源跨平台XML解析器-LIBXML2--库-hpux 11/ia64,源代码可从http://xmlsoft.org/downloads.html或资源“开源跨平台XML解析器-LIBXML2--C源代码及VC6工程文件”获取
Libxml2 是一个xml c语言版的解析器,本来是为Gnome项目开发的工具,是一个基于MIT License的免费开源软件。它除了支持c语言版以外,还支持c++、PHP、Pascal、Ruby、Tcl等语言的绑定,能在Windows、Linux、Solaris、...
解析xml文件的通用类,使用libxml实现边下载边解析,下载使用ASI开源库. 可以设置最外边需要解析的tag