最近的項目中有圖文直播功能,這個功能需要把服務器返回的HTML字符串轉為富文本NSAttributeString然后顯示出來慷垮。然后這個HTML字符串是已經過服務器的處理唁奢,只留下<a>矿卑、<img>否淤、<span>悄但、<strong>這幾個標簽,這篇文章主要關注如何對上面的HTML進行parse然后生成對應的富文本
工具
OCGumob:
一款基于Google的Gumbo寫的Objetive-C的HTML 文本解析器
用法:
OCGumboDocument *document = [[OCGumboDocument alloc] initWithHTMLString:htmlString];
OCGumboElement *root = document.rootElement;
//document: do something with the document.
//rootElement: do something with the html tree.
Class Description
OCGumboDocument the root of a document tree //類似DOM的根
OCGumboElement an element in an HTML document //OCGumboNode a single node in the document tree //DOM的節(jié)點
OCGumboText the textual content of an elementDOM //節(jié)點的文本
OCGumboAttribute an attribute of an Element object//DOM節(jié)點的屬性
轉換過程
首先創(chuàng)建OCGumboDocument
NSString *path = [[NSBundle mainBundle] pathForResource:@"test" ofType:@"html"];
NSString *htmlString = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:&error];
NSMutableAttributedString *attr = [NSMutableAttributedString new];
if (!error) {
NSLog(@"%@", htmlString);
OCGumboDocument *document = [[OCGumboDocument alloc] initWithHTMLString:htmlString];
OCGumboElement *body = document.body;
NSMutableDictionary *attributeDict = [NSMutableDictionary new];////空的字典石抡,用來儲存HTML中指定標簽的內容
[self logNode:body dic:attributeDict content:attr];//對HTML文本進行解析
}
重點在于檐嚣,首先初始化空的目標富文本NSMutableAttributeString,和空的屬性字典NSMutableDictionary, 然后遞歸遍歷OCGumboDocument中的OCGumboNode汁雷,判斷每個Node是OCGumboText還是OCGumboElement净嘀,若是前者則抽取出來文本并使用屬性字典的內容進行初始化并拼接到目標富文本上,若是后者則抽取出來想要的標簽的屬性并放到屬性字典中待用
- (void)logNode:(OCGumboNode *)node dic:(NSMutableDictionary *)dic content:(NSMutableAttributedString *)content {
NSLog(@"childNode count %ld",node.childNodes.count);
NSMutableDictionary *copyDict = [dic mutableCopy];
for (int i = 0; i< node.childNodes.count; i++) {
OCGumboNode *child = node.childNodes[i];
if ([child isKindOfClass:[OCGumboText class]]) { //node為OCGumboText類型時候侠讯,它的nodeValue值就是HTML里面的普通文本
OCGumboText *test = (OCGumboText *)child;
if ([child.nodeName isEqualToString:@"#text"]) {
NSMutableAttributedString *subContent = [[NSMutableAttributedString alloc] initWithString:child.nodeValue attributes:@{NSForegroundColorAttributeName: [UIColor blackColor], NSFontAttributeName:[UIFont systemFontOfSize:15]}];//根據默認的顏色和字體生成普通的NSAttributeString
NSLog(@"========== textNode ===========");
NSLog(@" nodeName: %@, nodeValue:%@", child.nodeName, child.nodeValue);
NSLog(@"text: %@", test.data);
NSLog(@"========================== \n\n");
if (copyDict.count > 0) {
//對之前掃描到的屬性字段進行遍歷,并把屬性設置到NSAtributeString上
[copyDict enumerateKeysAndObjectsUsingBlock:^(NSString* _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {
if ([key isEqualToString:@"color"]) {
[subContent addAttribute:NSForegroundColorAttributeName value:obj range:NSMakeRange(0, subContent.string.length)];
}
if ([key isEqualToString:@"strong"]) {
[subContent addAttribute:NSFontAttributeName value:[UIFont boldSystemFontOfSize:20] range:NSMakeRange(0, subContent.string.length)];
}
}];
}
[content appendAttributedString:subContent];
}
}
if ([child isKindOfClass:[OCGumboElement class]]) { //判斷是否是普通的node
NSArray *attributeArray = ((OCGumboElement *)child).attributes;
NSLog(@"************* attrbuteNode *************");
NSLog(@" nodeName: %@, nodeValue:%@", child.nodeName, child.nodeValue);
NSMutableDictionary *dic1 = [dic mutableCopy];
if ([child.nodeName isEqualToString:@"span"]) { //判斷是否是span標簽
for (OCGumboAttribute *attr in attributeArray) {
NSLog(@"name: %@暑刃, value: %@",attr.name,attr.value);
if ([attr.name isEqualToString:@"style"]) { //判斷是否是style屬性
if ([attr.value containsString:@"color"]) { //判斷style屬性中是否顏色,有則取出來
unsigned rgbValue;
NSScanner *scanner = [NSScanner scannerWithString:attr.value];
[scanner scanUpToString:@"color:#" intoString:NULL];
[scanner scanString:@"color:#" intoString:NULL];
[scanner scanHexInt:&rgbValue];
if (rgbValue > 0) {
UIColor *color = [UIColor colorWithRed:((rgbValue & 0xFF0000) >> 16)/255.0 green:((rgbValue & 0xFF00) >> 8)/255.0 blue:(rgbValue & 0xFF)/255.0 alpha:1.0];
dic1[@"color"] = color;
}
}
}
}
}
if ([child.nodeName isEqualToString:@"strong"]) { //判斷是否是strong標簽
dic1[@"strong"] = @(1);
}
if ([child.nodeName isEqualToString:@"img"]) { //判斷是否img標簽
for (OCGumboAttribute *attr in attributeArray) {
NSLog(@"name: %@厢漩, value: %@",attr.name,attr.value);
if ([attr.name isEqualToString:@"src"]) { //抽出img的src屬性 并生成相應的NSAtributeString拼接上去
NSString *img = attr.value;
NSLog(@"img: %@",img);
NSAttributedString *imgstr = [[NSAttributedString alloc]initWithString:@"img" attributes:@{NSForegroundColorAttributeName: [UIColor blueColor],NSFontAttributeName:[UIFont systemFontOfSize:15]}];
[content appendAttributedString:imgstr];
}
}
}
NSLog(@"************************** \n\n");
NSLog(@"> > > > > > > > > > > > > > > \n\n");
[self logNode:child dic:dic1 content:content];
}
}
}
當對HTML解析完以后我們就擁有完整的NSAttributeString,這時候只要通過YYText就能把這個富文本顯示出來