前言:做IOS开发,大家应该用到TouchXML这个每三方类库,其实它解析xml的根本还是用到了libxml来解析,
libxml是用C语言写的,只不过TouchXML把libxml封装成了OC,方便我们调用。大家理解了下面libxml的一些简单操作,
那对于大家理解TouchXML更有作用,会是对编程的一个提升
1 //
2 // ViewController.m
3 // drawertest
4 //
5 // Created by vincent_guo on 13-5-8.
6 //
7 //
8
9 #import "ViewController.h"
10 #import "NSString+Kwok.h"
11
12 #include <libxml/tree.h>
13 #include <libxml/xmlreader.h>
14 #include <libxml/parser.h>
15 #include <libxml/xpath.h>
16
17
18 @property(nonatomic,retain)NSMutableArray *computers;
19 @end
20
21 @implementation ViewController
22
23 - (void)viewDidLoad
24 {
25 [super viewDidLoad];
26 self.computers = [NSMutableArray array];
27 [self.computers addObject:@"MacBook Pro"];
28 [self.computers addObject:@"Lenovo E40"];
29 }
30
31 //这里本人创建一个xml文件的内容,方便大家参照着解读代码
32 //<?xml version="1.0" encoding="UTF-8"?>
33 //<vincent>
34 // <computers count="2">
35 // <computer>MacBook Pro</computer>
36 // <computer>Lenovo E40</computer>
37 // </computers>
38 // <telephone>Sony Ericsson索爱</telephone>
39 //</vincent>
40
41 //创建一个xml
42 -(void)libxmlCreate{
43 //xml文件路径 本人放在ios沙盒的Document目录下
44 NSString *xmlFilePath = [@"text.xml" appendFileNameBehindDocument];
45
46 xmlDocPtr xmlDoc = xmlNewDoc(BAD_CAST("1.0"));//xml的版本1.0
47 xmlNodePtr rootEle = xmlNewNode(NULL, BAD_CAST("vincent"));//创建根节点
48 xmlDocSetRootElement(xmlDoc, rootEle);//将rootEle节点加在xml的根节点
49
50 //New一个节点
51 xmlNodePtr computersEle = xmlNewNode(NULL, BAD_CAST("computers"));
52 //往computers节点添加属性
53 xmlNewProp(computersEle, BAD_CAST("count"), BAD_CAST("2"));
54 //添加computers节点到根节点下
55 xmlAddChild(rootEle, computersEle);
56
57 //下面的添加都是根上面一样的思路,希望大家看得明白
58 int cont = self.computers.count;
59 for (int i = 0; i < cont; i++) {
60 NSString *band = [self.computers objectAtIndex:i];
61 xmlNodePtr computerEle = xmlNewNode(NULL, BAD_CAST("computer"));
62 xmlNodeSetContent(computerEle, (const xmlChar *)[band cStringUsingEncoding:NSUTF8StringEncoding]);
63 xmlAddChild(computersEle, computerEle);
64 }
65
66 xmlNodePtr telephoneEle = xmlNewNode(NULL, BAD_CAST("telephone"));
67 xmlNodeSetContent(telephoneEle, BAD_CAST("Sony Ericsson索爱"));
68 xmlAddChild(rootEle, telephoneEle);
69
70 xmlSaveFormatFileEnc([xmlFilePath cStringUsingEncoding:NSUTF8StringEncoding], xmlDoc, "UTF-8", 1);//保存
71 xmlFreeDoc(xmlDoc);//释放内存
72
73 }
74
75 -(void)libxmlRead{
76 NSString *xmlFilePath = [@"text.xml" appendFileNameBehindDocument];
77 xmlTextReaderPtr reader = xmlNewTextReaderFilename((const char *)[xmlFilePath cStringUsingEncoding:NSUTF8StringEncoding]);
78 if (reader) {
79 char *temp;
80 char *value;
81 NSString *element;
82 while (TRUE) {
83 if (!xmlTextReaderRead(reader)){
84 NSLog(@"退出解析:break");
85 break;}
86 int type = xmlTextReaderNodeType(reader);
87 if ( type == XML_READER_TYPE_ELEMENT) {
88 temp = (char *)xmlTextReaderConstName(reader);//读取标签
89 element = [NSString stringCToOCUTF8:temp];
90
91 if ([element isEqualToString:@"computers"]) {
92 value = (char *)xmlTextReaderGetAttribute(reader, BAD_CAST("count"));
93 NSLog(@"解析标签:%@ count=%@",element,[NSString stringCToOCUTF8:value]);
94
95 }
96
97 if ([element isEqualToString:@"computer"]) {
98 value = (char *)xmlTextReaderReadString(reader);
99 NSLog(@"解析标签:%@ value=%@",element,[NSString stringCToOCUTF8:value]);
100 }
101
102 if ([element isEqualToString:@"telephone"]) {
103 value = (char *)xmlTextReaderReadString(reader);
104 NSLog(@"解析标签:%@ value=%@",element,[NSString stringCToOCUTF8:value]);
105 //读取标签内容
106 }
107 }
108
109 //读取Tag的内容
110 if (type == XML_READER_TYPE_TEXT) {
111 temp = (char*)xmlTextReaderConstValue(reader);
112 NSLog(@"XML_READER_TYPE_TEXT:%@",[NSString stringCToOCUTF8:temp]);
113 }
114
115 if (type == XML_READER_TYPE_END_ELEMENT) {
116
117 }
118
119
120 }
121 }
122
123 xmlFreeTextReader(reader);
124 }
125
126 xmlXPathObjectPtr get_nodeset(xmlDocPtr doc, const xmlChar *xpath) {
127 xmlXPathContextPtr context;
128 xmlXPathObjectPtr result;
129 context = xmlXPathNewContext(doc);
130 if (context == NULL) {
131 printf("context is NULL/n");
132 return NULL;
133 }
134
135 result = xmlXPathEvalExpression(xpath, context);
136 xmlXPathFreeContext(context);
137 if (result == NULL) {
138 printf("xmlXPathEvalExpression return NULL/n");
139 return NULL;
140 }
141 if (xmlXPathNodeSetIsEmpty(result->nodesetval)) {
142 xmlXPathFreeObject(result);
143 printf("nodeset is empty/n");
144 return NULL;
145 }
146 return result;
147 }
148
149 -(void)libxmlUpdate{//使用xpath解析得到一个节点,然后再更新内容
150 NSString *xmlFilePath = [@"text.xml" appendFileNameBehindDocument];//文件路径
151
152 xmlChar *xpath = BAD_CAST("/vincent/computers/computer");//xpath的正则表达式
153
154 //得到一个xmlDocPtr 其实xmlDocPtr就是一个指向结构体的指针
155 xmlDocPtr xmlDoc = xmlReadFile((char *)[xmlFilePath cStringUsingEncoding:NSUTF8StringEncoding], "UTF-8", 1);
156 xmlNodePtr curNode;
157
158 //get_nodeset方法是上面的一个方法,不是libxml里面的方法
159 xmlXPathObjectPtr app_result = get_nodeset(xmlDoc,xpath);
160 if (app_result) {
161 //得到查询出来节点的聚合(set)
162 xmlNodeSetPtr nodeSet = app_result -> nodesetval;
163
164 //nodeSet -> nodeNr 是访问nodeSet里面nodeNr的一个属性 nodeNr就是查出来的节点个数
165 for (int i=0; i< nodeSet -> nodeNr; i++) {
166 curNode = nodeSet -> nodeTab[i];//遍历节点
167
168 //得到节点里面的内容
169 char *temp = (char *)xmlNodeGetContent(curNode);
170
171 //输出节点内容 stringCToOCUTF8这个方法是本人自己写的,将char*转成NSString
172 NSLog(@"%@",[NSString stringCToOCUTF8:temp ]);
173 if (i == 0) {
174 //改变第一个computer节点的内容然后保存
175 xmlNodeSetContent(curNode,BAD_CAST("MacBook Air"));
176 xmlSaveFormatFileEnc([xmlFilePath cStringUsingEncoding:NSUTF8StringEncoding], xmlDoc, "UTF-8", 1);
177 }
178 }
179 }
180 xmlXPathFreeObject(app_result);//释放内存
181 xmlFreeDoc(xmlDoc);
182 }
183
184
185
186 @end