首页 > 代码库 > 使用libxml2进行xml开发(一)
使用libxml2进行xml开发(一)
(一)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
http://www.ualberta.ca/dept/aict/uts/software/solaris9/sparc/patches/solaris/9_Recommended/114014-18/SUNWlxmlS/reloc/usr/share/src/libxml2/example/gjobread.c
http://www.ualberta.ca/dept/aict/uts/software/solaris9/sparc/patches/solaris/9_Recommended/114014-18/SUNWlxmlS/reloc/usr/share/src/libxml2/example/gjobs.xml
笔者在编译成功后,运行的时候遇到过如下的一个错误
“无法定位程序输入点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 it107 */108 static jobPtr109 parseJob(xmlDocPtr doc, xmlNsPtr ns, xmlNodePtr cur) {110 jobPtr ret = NULL;111 112 DEBUG("parseJob\n");113 /*114 * allocate the struct115 */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 it153 */154 static void155 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 Jobs172 */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 gJobPtr180 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 kind195 */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 void267 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_VERSION283 xmlKeepBlanksDefault(0);284 285 for (i = 1; i < argc ; i++) {286 cur = parseGjobFile(argv[i]);287 if ( cur )288 handleGjob(cur);289 else290 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 }
1 <?xml version="1.0"?> 2 <gjob:Helping xmlns:gjob="http://www.gnome.org/some-location"> 3 <gjob:Jobs> 4 5 <gjob:Job> 6 <gjob:Project ID="3"/> 7 <gjob:Application>GBackup</gjob:Application> 8 <gjob:Category>Development</gjob:Category> 9 10 <gjob:Update>11 <gjob:Status>Open</gjob:Status>12 <gjob:Modified>Mon, 07 Jun 1999 20:27:45 -0400 MET DST</gjob:Modified>13 <gjob:Salary>USD 0.00</gjob:Salary>14 </gjob:Update>15 16 <gjob:Developers>17 <gjob:Developer>18 </gjob:Developer>19 </gjob:Developers>20 21 <gjob:Contact>22 <gjob:Person>Nathan Clemons</gjob:Person>23 <gjob:Email>nathan@windsofstorm.net</gjob:Email>24 <gjob:Company>25 </gjob:Company>26 <gjob:Organisation>27 </gjob:Organisation>28 <gjob:Webpage>29 </gjob:Webpage>30 <gjob:Snailmail>31 </gjob:Snailmail>32 <gjob:Phone>33 </gjob:Phone>34 </gjob:Contact>35 36 <gjob:Requirements>37 The program should be released as free software, under the GPL.38 </gjob:Requirements>39 40 <gjob:Skills>41 </gjob:Skills>42 43 <gjob:Details>44 A GNOME based system that will allow a superuser to configure 45 compressed and uncompressed files and/or file systems to be backed 46 up with a supported media in the system. This should be able to 47 perform via find commands generating a list of files that are passed 48 to tar, dd, cpio, cp, gzip, etc., to be directed to the tape machine 49 or via operations performed on the filesystem itself. Email 50 notification and GUI status display very important.51 </gjob:Details>52 53 </gjob:Job>54 55 </gjob:Jobs>56 </gjob:Helping>