(一)Windows下使用MinGW和Code::Blocks环境配置libxml2
笔者此次是在windows 7下使用MinGW和Code::Blocks开发C程式的,手上的一个项目需要使用socket通讯接收远端主机发来的xml报文,使用C程式解析,所以需要配置libxml2。
首先先到http://xmlsoft.org/sources/win32/下载好libxml2、iconv和zlib的包,并将其对应的bin、include、lib中的内容复制到MinGW对应的bin、include、lib目录中去(libxml2是基于iconv和zlib的
在CB中建立好一个工程后,在settings->compiler->linker settings中添加上述包中的lib(已经添加到MinGW\lib下了),我们可以用libxml2官方的一个例子来测试我们的配置:
将gjobs.xml放在工程文件夹中,将其设置为输入 Project->set programs' arguments
笔者在编译成功后,运行的时候遇到过如下的一个错误
“无法定位程序输入点gzdirect于动态链接库zlib1.dll”
解决办法是使用http://www.zlib.net/下载的最新的zlib1.dll替换WINDOWS/system32文件夹下的zlib1.dll (window下优先使用system32下的这个dll,而在安装某些软件时会将它们的zlib1.dll放到system32中,造成版本过低)
运行结果:
附gjobread.c和gjobs.xml源码
1 /* 2 * gjobread.c : a small test program for gnome jobs XML format 3 * 4 * See Copyright for the status of this software. 5 * 6 * Daniel.Veillard@w3.org 7 */ 8 9 #include <stdio.h> 10 #include <string.h> 11 #include <stdlib.h> 12 13 /* 14 * This example should compile and run indifferently with libxml-1.8.8 + 15 * and libxml2-2.1.0 + 16 * Check the COMPAT comments below 17 */ 18 19 /* 20 * COMPAT using xml-config --cflags to get the include path this will 21 * work with both 22 */ 23 #include <libxml/xmlmemory.h> 24 #include <libxml/parser.h> 25 26 #define DEBUG(x) printf(x) 27 28 /* 29 * A person record 30 * an xmlChar * is really an UTF8 encoded char string (0 terminated) 31 */ 32 typedef struct person { 33 xmlChar *name; 34 xmlChar *email; 35 xmlChar *company; 36 xmlChar *organisation; 37 xmlChar *smail; 38 xmlChar *webPage; 39 xmlChar *phone; 40 } person, *personPtr; 41 42 /* 43 * And the code needed to parse it 44 */ 45 static personPtr 46 parsePerson(xmlDocPtr doc, xmlNsPtr ns, xmlNodePtr cur) { 47 personPtr ret = NULL; 48 49 DEBUG("parsePerson\n"); 50 /* 51 * allocate the struct 52 */ 53 ret = (personPtr) malloc(sizeof(person)); 54 if (ret == NULL) { 55 fprintf(stderr,"out of memory\n"); 56 return(NULL); 57 } 58 memset(ret, 0, sizeof(person)); 59 60 /* We don't care what the top level element name is */ 61 /* COMPAT xmlChildrenNode is a macro unifying libxml1 and libxml2 names */ 62 cur = cur->xmlChildrenNode; 63 while (cur != NULL) { 64 if ((!xmlStrcmp(cur->name, (const xmlChar *)"Person")) && 65 (cur->ns == ns)) 66 ret->name = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); 67 if ((!xmlStrcmp(cur->name, (const xmlChar *)"Email")) && 68 (cur->ns == ns)) 69 ret->email = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); 70 cur = cur->next; 71 } 72 73 return(ret); 74 } 75 76 /* 77 * and to print it 78 */ 79 static void 80 printPerson(personPtr cur) { 81 if (cur == NULL) return; 82 printf("------ Person\n"); 83 if (cur->name) printf(" name: %s\n", cur->name); 84 if (cur->email) printf(" email: %s\n", cur->email); 85 if (cur->company) printf(" company: %s\n", cur->company); 86 if (cur->organisation) printf(" organisation: %s\n", cur->organisation); 87 if (cur->smail) printf(" smail: %s\n", cur->smail); 88 if (cur->webPage) printf(" Web: %s\n", cur->webPage); 89 if (cur->phone) printf(" phone: %s\n", cur->phone); 90 printf("------\n"); 91 } 92 93 /* 94 * a Description for a Job 95 */ 96 typedef struct job { 97 xmlChar *projectID; 98 xmlChar *application; 99 xmlChar *category; 100 personPtr contact; 101 int nbDevelopers; 102 personPtr developers[100]; /* using dynamic alloc is left as an exercise */ 103 } job, *jobPtr; 104 105 /* 106 * And the code needed to parse it 107 */ 108 static jobPtr 109 parseJob(xmlDocPtr doc, xmlNsPtr ns, xmlNodePtr cur) { 110 jobPtr ret = NULL; 111 112 DEBUG("parseJob\n"); 113 /* 114 * allocate the struct 115 */ 116 ret = (jobPtr) malloc(sizeof(job)); 117 if (ret == NULL) { 118 fprintf(stderr,"out of memory\n"); 119 return(NULL); 120 } 121 memset(ret, 0, sizeof(job)); 122 123 /* We don't care what the top level element name is */ 124 cur = cur->xmlChildrenNode; 125 while (cur != NULL) { 126 127 if ((!xmlStrcmp(cur->name, (const xmlChar *) "Project")) && 128 (cur->ns == ns)) { 129 ret->projectID = xmlGetProp(cur, (const xmlChar *) "ID"); 130 if (ret->projectID == NULL) { 131 fprintf(stderr, "Project has no ID\n"); 132 } 133 } 134 if ((!xmlStrcmp(cur->name, (const xmlChar *) "Application")) && 135 (cur->ns == ns)) 136 ret->application = 137 xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); 138 if ((!xmlStrcmp(cur->name, (const xmlChar *) "Category")) && 139 (cur->ns == ns)) 140 ret->category = 141 xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); 142 if ((!xmlStrcmp(cur->name, (const xmlChar *) "Contact")) && 143 (cur->ns == ns)) 144 ret->contact = parsePerson(doc, ns, cur); 145 cur = cur->next; 146 } 147 148 return(ret); 149 } 150 151 /* 152 * and to print it 153 */ 154 static void 155 printJob(jobPtr cur) { 156 int i; 157 158 if (cur == NULL) return; 159 printf("======= Job\n"); 160 if (cur->projectID != NULL) printf("projectID: %s\n", cur->projectID); 161 if (cur->application != NULL) printf("application: %s\n", cur->application); 162 if (cur->category != NULL) printf("category: %s\n", cur->category); 163 if (cur->contact != NULL) printPerson(cur->contact); 164 printf("%d developers\n", cur->nbDevelopers); 165 166 for (i = 0;i < cur->nbDevelopers;i++) printPerson(cur->developers[i]); 167 printf("======= \n"); 168 } 169 170 /* 171 * A pool of Gnome Jobs 172 */ 173 typedef struct gjob { 174 int nbJobs; 175 jobPtr jobs[500]; /* using dynamic alloc is left as an exercise */ 176 } gJob, *gJobPtr; 177 178 179 static gJobPtr 180 parseGjobFile(char *filename) { 181 xmlDocPtr doc; 182 gJobPtr ret; 183 jobPtr curjob; 184 xmlNsPtr ns; 185 xmlNodePtr cur; 186 187 /* 188 * build an XML tree from a the file; 189 */ 190 doc = xmlParseFile(filename); 191 if (doc == NULL) return(NULL); 192 193 /* 194 * Check the document is of the right kind 195 */ 196 197 cur = xmlDocGetRootElement(doc); 198 if (cur == NULL) { 199 fprintf(stderr,"empty document\n"); 200 xmlFreeDoc(doc); 201 return(NULL); 202 } 203 ns = xmlSearchNsByHref(doc, cur, 204 (const xmlChar *) "http://www.gnome.org/some-location"); 205 if (ns == NULL) { 206 fprintf(stderr, 207 "document of the wrong type, GJob Namespace not found\n"); 208 xmlFreeDoc(doc); 209 return(NULL); 210 } 211 if (xmlStrcmp(cur->name, (const xmlChar *) "Helping")) { 212 fprintf(stderr,"document of the wrong type, root node != Helping"); 213 xmlFreeDoc(doc); 214 return(NULL); 215 } 216 217 /* 218 * Allocate the structure to be returned. 219 */ 220 ret = (gJobPtr) malloc(sizeof(gJob)); 221 if (ret == NULL) { 222 fprintf(stderr,"out of memory\n"); 223 xmlFreeDoc(doc); 224 return(NULL); 225 } 226 memset(ret, 0, sizeof(gJob)); 227 228 /* 229 * Now, walk the tree. 230 */ 231 /* First level we expect just Jobs */ 232 cur = cur->xmlChildrenNode; 233 while ( cur && xmlIsBlankNode ( cur ) ) 234 { 235 cur = cur -> next; 236 } 237 if ( cur == 0 ) 238 return ( NULL ); 239 if ((xmlStrcmp(cur->name, (const xmlChar *) "Jobs")) || (cur->ns != ns)) { 240 fprintf(stderr,"document of the wrong type, was '%s', Jobs expected", 241 cur->name); 242 fprintf(stderr,"xmlDocDump follows\n"); 243 xmlDocDump ( stderr, doc ); 244 fprintf(stderr,"xmlDocDump finished\n"); 245 xmlFreeDoc(doc); 246 free(ret); 247 return(NULL); 248 } 249 250 /* Second level is a list of Job, but be laxist */ 251 cur = cur->xmlChildrenNode; 252 while (cur != NULL) { 253 if ((!xmlStrcmp(cur->name, (const xmlChar *) "Job")) && 254 (cur->ns == ns)) { 255 curjob = parseJob(doc, ns, cur); 256 if (curjob != NULL) 257 ret->jobs[ret->nbJobs++] = curjob; 258 if (ret->nbJobs >= 500) break; 259 } 260 cur = cur->next; 261 } 262 263 return(ret); 264 } 265 266 static void 267 handleGjob(gJobPtr cur) { 268 int i; 269 270 /* 271 * Do whatever you want and free the structure. 272 */ 273 printf("%d Jobs registered\n", cur->nbJobs); 274 for (i = 0; i < cur->nbJobs; i++) printJob(cur->jobs[i]); 275 } 276 277 int main(int argc, char **argv) { 278 int i; 279 gJobPtr cur; 280 281 /* COMPAT: Do not genrate nodes for formatting spaces */ 282 LIBXML_TEST_VERSION 283 xmlKeepBlanksDefault(0); 284 285 for (i = 1; i < argc ; i++) { 286 cur = parseGjobFile(argv[i]); 287 if ( cur ) 288 handleGjob(cur); 289 else 290 fprintf( stderr, "Error parsing file '%s'\n", argv[i]); 291 292 } 293 294 /* Clean up everything else before quitting. */ 295 xmlCleanupParser(); 296 297 return(0); 298 }