ios 解析html
xml,json都有大量的库来解析,我们如何解析html呢?
TFHpple是一个小型的封装,可以用来解析html,它是对libxml的封装,语法是xpath。
今天我看到一个直接用libxml来解析html,参看:http://www.cocoanetics.com/2011/09/taming-html-parsing-with-libxml-1/#comment-3090 那张图画得一目了然,很值得收藏。这个文章中的源码不能遍历所有的html,我做了一点修改可以将html遍历打印出来
// NSData data contains the document data
// encoding is the NSStringEncoding of the data
// baseURL the documents base URL, i.e. location
CFStringEncoding cfenc = CFStringConvertNSStringEncodingToEncoding(encoding);
CFStringRef cfencstr = CFStringConvertEncodingToIANACharSetName(cfenc);
const char *enc = CFStringGetCStringPtr(cfencstr, 0);
htmlDocPtr _htmlDocument = htmlReadDoc([data bytes],
[[baseURL absoluteString] UTF8String],
enc,
XML_PARSE_NOERROR | XML_PARSE_NOWARNING);
if (_htmlDocument)
{
xmlFreeDoc(_htmlDocument);
}
xmlNodePtr currentNode = (xmlNodePtr)_htmlDocument;
while (currentNode)
{
// output node if it is an element
if (currentNode->type == XML_ELEMENT_NODE)
{
NSMutableArray *attrArray = [NSMutableArray array];
for (xmlAttrPtr attrNode = currentNode->properties; attrNode; attrNode = attrNode->next)
{
xmlNodePtr contents = attrNode->children;
[attrArray addObject:[NSString stringWithFormat:@"%s='%s'", attrNode->name, contents->content]];
}
NSString *attrString = [attrArray componentsJoinedByString:@" "];
if ([attrString length])
{
attrString = [@" " stringByAppendingString:attrString];
}
NSLog(@"<%s%@>", currentNode->name, attrString);
}
else if (currentNode->type == XML_TEXT_NODE)
{
//NSLog(@"%s", currentNode->content);
NSLog(@"%@", [NSString stringWithCString:(const char *)currentNode->content encoding:NSUTF8StringEncoding]);
}
else if (currentNode->type == XML_COMMENT_NODE)
{
NSLog(@"/* %s */", currentNode->name);
}
if (currentNode && currentNode->children)
{
currentNode = currentNode->children;
}
else if (currentNode && currentNode->next)
{
currentNode = currentNode->next;
}
else
{
currentNode = currentNode->parent;
// close node
if (currentNode && currentNode->type == XML_ELEMENT_NODE)
{
NSLog(@"</%s>", currentNode->name);
}
if (currentNode->next)
{
currentNode = currentNode->next;
}
else
{
while(currentNode)
{
currentNode = currentNode->parent;
if (currentNode && currentNode->type == XML_ELEMENT_NODE)
{
NSLog(@"</%s>", currentNode->name);
if (strcmp((const char *)currentNode->name, "table") == 0)
{
NSLog(@"over");
}
}
if (currentNode == nodes->nodeTab[0])
{
break;
}
if (currentNode && currentNode->next)
{
currentNode = currentNode->next;
break;
}
}
}
}
if (currentNode == nodes->nodeTab[0])
{
break;
}
}
不过我还是喜欢用TFHpple,因为它很简单,也好用,但是它的功能不是很完完善。比如,不能获取children node,我就写了两个方法,一个是获取children node,一个是获取所有的contents. 还有node的属性content的key与node's content的key一样,都是@"nodeContent", 正确情况下属性的应是@"attributeContent",
所以我写了这个方法,同时修改node属性的content key.
NSDictionary *DictionaryForNode2(xmlNodePtr currentNode, NSMutableDictionary *parentResult)
{
NSMutableDictionary *resultForNode = [NSMutableDictionary dictionary];
if (currentNode->name)
{
NSString *currentNodeContent =
[NSString stringWithCString:(const char *)currentNode->name encoding:NSUTF8StringEncoding];
[resultForNode setObject:currentNodeContent forKey:@"nodeName"];
}
if (currentNode->content)
{
NSString *currentNodeContent = [NSString stringWithCString:(const char *)currentNode->content encoding:NSUTF8StringEncoding];
if (currentNode->type == XML_TEXT_NODE)
{
if (currentNode->parent->type == XML_ELEMENT_NODE)
{
[parentResult setObject:currentNodeContent forKey:@"nodeContent"];
return nil;
}
if (currentNode->parent->type == XML_ATTRIBUTE_NODE)
{
[parentResult
setObject:
[currentNodeContent
stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]
forKey:@"attributeContent"];
return nil;
}
}
}
xmlAttr *attribute = currentNode->properties;
if (attribute)
{
NSMutableArray *attributeArray = [NSMutableArray array];
while (attribute)
{
NSMutableDictionary *attributeDictionary = [NSMutableDictionary dictionary];
NSString *attributeName =
[NSString stringWithCString:(const char *)attribute->name encoding:NSUTF8StringEncoding];
if (attributeName)
{
[attributeDictionary setObject:attributeName forKey:@"attributeName"];
}
if (attribute->children)
{
NSDictionary *childDictionary = DictionaryForNode2(attribute->children, attributeDictionary);
if (childDictionary)
{
[attributeDictionary setObject:childDictionary forKey:@"attributeContent"];
}
}
if ([attributeDictionary count] > 0)
{
[attributeArray addObject:attributeDictionary];
}
attribute = attribute->next;
}
if ([attributeArray count] > 0)
{
[resultForNode setObject:attributeArray forKey:@"nodeAttributeArray"];
}
}
xmlNodePtr childNode = currentNode->children;
if (childNode)
{
NSMutableArray *childContentArray = [NSMutableArray array];
while (childNode)
{
NSDictionary *childDictionary = DictionaryForNode2(childNode, resultForNode);
if (childDictionary)
{
[childContentArray addObject:childDictionary];
}
childNode = childNode->next;
}
if ([childContentArray count] > 0)
{
[resultForNode setObject:childContentArray forKey:@"nodeChildArray"];
}
}
return resultForNode;
}
TFHppleElement.m里加了两个key 常量
NSString * const TFHppleNodeAttributeContentKey = @"attributeContent";
NSString * const TFHppleNodeChildArrayKey = @"nodeChildArray";
并修改获取属性方法为:
- (NSDictionary *) attributes
{
NSMutableDictionary * translatedAttributes = [NSMutableDictionary dictionary];
for (NSDictionary * attributeDict in [node objectForKey:TFHppleNodeAttributeArrayKey]) {
[translatedAttributes setObject:[attributeDict objectForKey:TFHppleNodeAttributeContentKey]
forKey:[attributeDict objectForKey:TFHppleNodeAttributeNameKey]];
}
return translatedAttributes;
}
并添加获取children node 方法:
- (BOOL) hasChildren
{
NSArray *childs = [node objectForKey: TFHppleNodeChildArrayKey];
if (childs)
{
return YES;
}
return NO;
}
- (NSArray *) children
{
if ([self hasChildren])
return [node objectForKey: TFHppleNodeChildArrayKey];
return nil;
}
ios 解析html的更多相关文章
- IOS 解析XML文档
前段时间想找点事做,就是试着看能不能用豆瓣的API做点什么,于是就碰到了这个问题——XML解析. 老师还没讲,只能自己去查. XML文档解析主要有SAX和DOM两种模式,IOS上两种模式都可以用,这里 ...
- iOS解析crash日志:
iOS解析crash日志:我们在ios开发中会碰到的很多crash问题,如果Debug调试模式的话,我们可以往往很容易的根据log的输出定位到导致crash的原因,但对于已经上线的应用,或者是rele ...
- iOS解析XML数据
iOS中解析XML数据的类是 NSXMLParser,详细使用方法如下: 假设现在在内存中有XML的二进制数据对象(NSData):data(该数据可能来自网络,也可能是本地的文件数据),设置NSX ...
- iOS解析Server端返回JSON数据
在做quhao APP架构时,后台Server端使用了Java,提供WebService,而iOS和Android作为移动客户端.在做数据交互时,Server端返回JSON格式数据.由于iOS SDK ...
- ios解析XML和json数据
解析的基本概念所谓“解析”:从事先规定好的格式串中提取数据解析的前提:提前约定好格式.数据提供方按照格式提供数据.数据获取方按照格式获取数据iOS开发常见的解析:XML解析.JSON解析 一.XML数 ...
- IOS解析XML
XML也许是我们储存数据和通讯数据中最常见的一种简易方式,当我们来到XML的海洋时,我们会发现当我们用iPhone程序解析XML时,我们是有如此多的选项,让人眼花缭乱.iOS SDK本身就带有两种不同 ...
- IOS 解析XML数据
● 什么是XML ● 全称是Extensible Markup Language,译作“可扩展标记语言” ● 跟JSON一样,也是常用的一种用于交互的数据格式 ● 一般也叫XML文档(XML ...
- IOS 解析Json数据(NSJSONSerialization)
● 什么是JSON ● JSON是一种轻量级的数据格式,一般用于数据交互 ● 服务器返回给客户端的数据,一般都是JSON格式或者XML格式(文件下载除 外) ● JSON的格式很像OC中的字典和数组 ...
- iOS解析数据时Error=3840
1.解析JSon数据格式出错的问题 unescaped control character around character XXXX 和 The data couldn’t be read beca ...
- iOS解析JSON字符串报错Error Domain=NSCocoaErrorDomain Code=3840 "Invalid escape sequence around character 586."
将服务器返回的JSON string转化成字典时报错: Error Domain=NSCocoaErrorDomain Code=3840 "Invalid escape sequence ...
随机推荐
- 使用htmlunit在线解析网页信息
前言 最近工作上遇到一个问题,后端有一个定时任务,需要用JAVA每天判断法定节假日.周末放假,上班等情况, 其实想单独通过逻辑什么的去判断中国法定节假日的放假情况,基本不可能,因为国家每一年的假期可能 ...
- Linux之格式化与挂载
格式化与挂载 一块硬盘要想被使用,要经过分区,格式化,挂载这三个步骤.前面我们讲过MBR分区和GPT分区. 下面我们就来讲一下如果格式化一个分区.其实很简单,一句话就能搞定了. 首先来查看一下sdb盘 ...
- MyEclipse 6.5 代码自动提示功能配置教程
1. 打开MyEclipse 6.0.1,然后“window”→“Preferences” 2. 选择“java”,展开,“Editor”,选择“Content Assist”. 3. 选择“Cont ...
- Python Memcached Script
介绍 利用 python 书写了 memcached 的启动等一类操作 尽量的实现脚本的复用性,以及脚本的可扩展性,已达到一劳永逸的效果, 并且添加了 memcached 监控搭建 memcached ...
- 嵌入式开发板iTOP4412学习开发板
网站:http://www.topeetboard.com 淘宝:https://item.taobao.com/item.htm?_u=okcahs0f42a&id=38712193806 ...
- c#分页读取GB文本文件
应用场景: a.我在做BI开发测试的时候,有可能面对source文件数GB的情况,如果使用一般的文本编辑器,则会卡死,或要等很久才能显示出来. b.有时候,我们使用ascii(01)或ascii(02 ...
- CentOS 7 安装Redis 2.8.7
1.下载软件: wget wget http://download.redis.io/releases/redis-2.8.7.tar.gz 2.解压软件并编译安装: tar -zxvf redis- ...
- 分享一个解决MySQL写入中文乱码的方法
分享一个解决MySQL写入中文乱码的方法 之前有发帖请教过如何解决MySQL写入中文乱码的问题.但没人会,或者是会的人不想回答.搜索网上的答案并尝试很多次无效,所以当时就因为这个乱码问题搁浅了一个软件 ...
- Zbrush遮罩边界该怎么实现羽化和锐化
很多情况下为了雕刻制图需要,在ZBrush®中不仅要使用边缘清晰的遮罩,有时还要将遮罩边缘变得模糊,做羽化效果.那么如何在ZBrush中实现羽化遮罩效果或锐化遮罩效果,本文将做详细讲解. 若有疑问可直 ...
- Java语法基础(二)----运算符
一.运算符: 运算符包括下面几种: 算术运算符 赋值运算符 比较运算符 逻辑运算符 位运算符 三目运算符 最不常用的是位运算符,但也是最接近计算机底层的. 1.算术运算符 (1)+的几种用法:加法.正 ...