[Linux C]利用libxml2解析xml文件
為了解析xml,可以使用Linux下默認安裝的libxml2。
/*a.c功能:利用libxml2解析xml文件 */#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <libgen.h> #include <libxml/xmlmemory.h> #include <libxml/parser.h> #include <libxml/xpath.h>int GetCurFilePath(char *lpOut) // get full path of the executable file {char chPath[BUFSIZ] = {0};int nRetVal = readlink("/proc/self/exe", chPath, sizeof(chPath)); // get full path of the current-executable fileif(nRetVal < 0){strcpy(lpOut, ".");return -1;}else{strcpy(lpOut, chPath);return 0;} }int GetCurDir(char *lpOut) // get directory-path of current executable-file {char chPath[BUFSIZ] = { 0 };if( GetCurFilePath(chPath) < 0 )return - 1;dirname(chPath); // dirname will change value of "chPath"(contain result)strcpy(lpOut, chPath); // copy result to out-paramreturn 0; }xmlDocPtr getdoc(char *docname) // 根據(jù)文件名得到文檔指針 {xmlDocPtr doc;doc = xmlParseFile(docname);if(doc == NULL){fprintf(stderr, "Document not parsed successfully.\n");return NULL;}return doc; }// 在文檔doc中解析xpath表達式,返回結果集指針 xmlXPathObjectPtr getnodeset(xmlDocPtr doc, xmlChar *xpath) {xmlXPathContextPtr context;xmlXPathObjectPtr result;context = xmlXPathNewContext(doc);if(context == NULL){printf("Error in xmlXPathNewContent\n");return NULL;}result = xmlXPathEvalExpression(xpath, context); // 在context中解析表達式xpathxmlXPathFreeContext(context); // 釋放contextif(result == NULL){printf("Error in xmlXPathEvalExpression\n");return NULL;}if(xmlXPathNodeSetIsEmpty(result->nodesetval)) // 解析表達式的結果集為空{xmlXPathFreeObject(result);printf("No result\n");return NULL;}return result; }// 解析xmlPath路徑的結點 void testReadXmlDoc(char *filepath, char *xmlPath) {xmlDocPtr doc = getdoc(filepath);if(NULL == doc)return ;xmlChar *xpath = (xmlChar*) xmlPath;xmlXPathObjectPtr result = getnodeset(doc, xpath); // 獲取結果集if(result){xmlNodeSetPtr nodeset = result->nodesetval;xmlChar *name, *value;printf("nodeset->nodeNr = %d\n", nodeset->nodeNr); // 打印結果集中結點個數(shù)for(int i = 0; i < nodeset->nodeNr; i++){xmlNodePtr cur = nodeset->nodeTab[i]; // productsprintf("cur->name = %s\n", cur->name);cur = cur->xmlChildrenNode;while(cur){if(xmlStrcmp(cur->name, (const xmlChar*) "text")) // cur->name不為"text"{printf("cur->name = %s\t", cur->name);name = xmlGetProp(cur, (const xmlChar*) "name"); // 獲取屬性值value = xmlGetProp(cur, (const xmlChar*) "value");printf("name = %s, value = %s\n", name, value);xmlFree(name);xmlFree(value);}cur = cur->next;}printf("\n");}xmlXPathFreeObject(result);}xmlFreeDoc(doc);xmlCleanupParser(); }int main(void) {char curDir[100] = {0};char docname[100] = {0};GetCurDir(curDir);strcpy(docname, curDir);strcat(docname, "/dprod.xml");testReadXmlDoc(docname, "/allproducts/products");return EXIT_SUCCESS; }makefile文件: CC=gcc CFLAGS= BIN=a INC=/usr/include/libxml2$(BIN): $(BIN).c$(CC) $(CFLAGS) -o $(BIN) $(BIN).c -I$(INC) -lxml2 -std=c99clean:rm -f *.o $(BIN)
xml文件(dprod.xml)內(nèi)容: <?xml version="1.0"?> <allproducts><products><product name="name11" value="value11" /><product name="name12" value="value12" /><product name="name13" value="value13" /><product name="name14" value="value14" /></products><products><product name="name21" value="value21" /><product name="name22" value="value22" /><product name="name23" value="value23" /></products><products><product name="name31" value="value31" /><product name="name32" value="value32" /></products> </allproducts>
編譯運行: [zcm@tmp #115]$make gcc -o a a.c -I/usr/include/libxml2 -lxml2 -std=c99 a.c: 在函數(shù)‘GetCurFilePath’中: a.c:18: 警告:隱式聲明函數(shù)‘readlink’ [zcm@tmp #116]$./a nodeset->nodeNr = 3 cur->name = products cur->name = product name = name11, value = value11 cur->name = product name = name12, value = value12 cur->name = product name = name13, value = value13 cur->name = product name = name14, value = value14cur->name = products cur->name = product name = name21, value = value21 cur->name = product name = name22, value = value22 cur->name = product name = name23, value = value23cur->name = products cur->name = product name = name31, value = value31 cur->name = product name = name32, value = value32[zcm@tmp #117]$
說明:對于編譯中出現(xiàn)的“a.c:18: 警告:隱式聲明函數(shù)‘readlink’”錯誤,實在不能明白。我查了下手冊,這個函數(shù)在unistd.h中,而且我也已經(jīng)#include了,為什么還會出現(xiàn)這個錯誤呢?
后來突然想到,可能是-std=c99的原因,將它改為-std=gnu99后,這個警告就沒有了!
--------------------------------------------------------------------------------------------------------------------------------------------------
修改了xml文件和上面源碼中的testReadXmlDoc()后,發(fā)現(xiàn)結果相當神奇,看來對libxml2的理解還是比較缺乏。
1. 修改xml文件內(nèi)容:
<?xml version="1.0"?> <allproducts><products>h1<product name="name11" value="value11" />h2<product name="name12" value="value12" />h3<product name="name13" value="value13" />h4<product name="name14" value="value14" />h5</products><products><product name="name21" value="value21" /><product name="name22" value="value22" /><product name="name23" value="value23" /></products><products><product name="name31" value="value31" />g1<product name="name32" value="value32" /> g2</products> </allproducts>2. 修改testReadXmlDoc()
// 解析xmlPath路徑的結點 void testReadXmlDoc(char *filepath, char *xmlPath) {xmlDocPtr doc = getdoc(filepath);if(NULL == doc)return ;xmlChar *xpath = (xmlChar*) xmlPath;xmlXPathObjectPtr result = getnodeset(doc, xpath); // 獲取結果集if(result){xmlNodeSetPtr nodeset = result->nodesetval;xmlChar *name, *value;printf("nodeset->nodeNr = %d\n", nodeset->nodeNr); // 打印結果集中結點個數(shù)for(int i = 0; i < nodeset->nodeNr; i++){xmlNodePtr cur = nodeset->nodeTab[i]; // productsprintf("cur->name = %s\n", cur->name);cur = cur->xmlChildrenNode;int ctext = 0;while(cur){if(xmlStrcmp(cur->name, (const xmlChar*) "text")) // cur->name不為"text"{printf("cur->name = %s\t", cur->name);name = xmlGetProp(cur, (const xmlChar*) "name"); // 獲取屬性值value = xmlGetProp(cur, (const xmlChar*) "value");printf("name = %s, value = %s\n", name, value);xmlFree(name);xmlFree(value);}else{ctext++;xmlChar *v = xmlNodeListGetString(doc, cur, 1);printf("cur->content = [%s], v = [%s]", cur->content, v); // cur->content獲取cur的內(nèi)容xmlFree(v);}cur = cur->next;}printf("ctext = %d\n", ctext);printf("\n");}xmlXPathFreeObject(result);}xmlFreeDoc(doc);xmlCleanupParser(); }
運行結果:
[zcm@tmp #168]$make gcc -o a a.c -I/usr/include/libxml2 -lxml2 -std=gnu99 [zcm@tmp #169]$./a nodeset->nodeNr = 3 cur->name = products cur->content = [h1], v = [h1h2h3h4h5]cur->name = product name = name11, value = value11 cur->content = [h2], v = [h2h3h4h5]cur->name = product name = name12, value = value12 cur->content = [h3], v = [h3h4h5]cur->name = product name = name13, value = value13 cur->content = [h4], v = [h4h5]cur->name = product name = name14, value = value14 cur->content = [h5], v = [h5]ctext = 5cur->name = products cur->content = [], v = []cur->name = product name = name21, value = value21 cur->content = [], v = []cur->name = product name = name22, value = value22 cur->content = [], v = []cur->name = product name = name23, value = value23 cur->content = [], v = []ctext = 4cur->name = products cur->content = [], v = [g1g2]cur->name = product name = name31, value = value31 cur->content = [g1], v = [g1g2]cur->name = product name = name32, value = value32 cur->content = [ g2], v = [ g2]ctext = 3[zcm@tmp #170]$由此可見,一般情況下,我們用的比較多的可能會是cur->content這個東西了!
補充:
在網(wǎng)上看到一個人的寫法,可以在解析xml文件時,直接忽略掉結點之間的無效空白。對于本文,就是將:
doc?=?xmlParseFile(docname); --->修改為:doc?=?xmlParseFile(docname, "UTF-8", XML_PARSE_NOBLANKS);? // 第3個參數(shù)是關鍵
總結
以上是生活随笔為你收集整理的[Linux C]利用libxml2解析xml文件的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 印度光伏巨头Adani与华为签署500M
- 下一篇: Linux下查看文件和文件夹大小的df和