linux c xml 編程。。
上一篇 / 下一篇 2007-04-23 06:27:04 / 個(gè)人分類:linux c 編程
最近在做linux c xml 編程測試。
在網(wǎng)絡(luò)上似乎找不到太多的資料。
我覺得 http://www.xmlsoft.org/tutorial/index.html
的教程不錯(cuò)。給大家介紹一下。。是英文,不過很簡單。相信做編程的人不會(huì)看不懂。。
給出國內(nèi)的一資料,寫得也很不錯(cuò)。(程序 我測試過了)
使用簡介
數(shù)據(jù)類型:
xmlChar 替代char,使用UTF-8編碼的一字節(jié)字符串。如果你的數(shù)據(jù)使用其它編碼,它必須被轉(zhuǎn)換到UTF-8才能使用libxml的函數(shù)。
XmlDoc 包含由解析文檔建立的樹結(jié)構(gòu),xmlDocPtr是指向這個(gè)結(jié)構(gòu)的指針。
xmlNodePtr and xmlNode 包含單一結(jié)點(diǎn)的結(jié)構(gòu)
xmlNodePtr是指向這個(gè)結(jié)構(gòu)的指針,它被用于遍歷文檔樹。
優(yōu)點(diǎn):1. 安裝、使用比較簡單,容易入門;2. 支持的編碼格式較多,能很好的解決中文問題(使用一個(gè)很簡單的編碼轉(zhuǎn)換函數(shù));3. 支持Xpath解析(這點(diǎn)對(duì)于任意定位xml文檔中的節(jié)點(diǎn)還是很有用的哦);4.支持Well-formed 和valid驗(yàn)證,具體而言支持DTD驗(yàn)證,Schema驗(yàn)證功能正在完善中(目前多數(shù)解析器都還不完全支持shema驗(yàn)證功能);5. 支持目前通用的Dom、Sax方式解析等等。
不足:1. 指針太多,使用不當(dāng)時(shí)就會(huì)出現(xiàn)錯(cuò)誤,在Linux系統(tǒng)中表現(xiàn)為常見的段錯(cuò)誤,同樣管理不當(dāng)易造成內(nèi)存泄漏;2.個(gè)人認(rèn)為內(nèi)面有些函數(shù)的功能設(shè)計(jì)的不是很好(比如獲取Xpath函數(shù),它不獲取節(jié)點(diǎn)屬性,這樣子有些情況會(huì)定位不準(zhǔn))。
在學(xué)習(xí)libxml2中,最好的學(xué)習(xí)手冊(cè)就是由官方開發(fā)者提供的開發(fā)手冊(cè)就是libxml2-devel-2.6.19,rpm –q –d libxml2獲得文檔路徑,就是它了。
關(guān)于xml
開始研究 LibXML2 庫之前,讓我們先來鞏固一下 XML 的相關(guān)基礎(chǔ)。XML 是一種基于文本的格式,它可用來創(chuàng)建能夠通過各種語言和平臺(tái)訪問的結(jié)構(gòu)化數(shù)據(jù)。它包括一系列類似 HTML 的標(biāo)記,并以樹型結(jié)構(gòu)來對(duì)這些標(biāo)記進(jìn)行排列。
例如,可參見清單 1 中介紹的簡單文檔。這是配置文件部分中研究的配置文件示例的簡化版本。為了更清楚地顯示 XML 的一般概念,所以對(duì)其進(jìn)行了簡化。
清單 1. 一個(gè)簡單的 XML 文件
<?xml version="1.0" encoding="UTF-8"?>
<files>
<owner>root</owner>
<action>delete</action>
<age units="days">10</age>
</files>
清單 1 中的第一行是 XML 聲明,它告訴負(fù)責(zé)處理 XML 的應(yīng)用程序,即解析器,將要處理的 XML 的版本。大部分的文件使用版本 1.0 編寫,但也有少量的版本 1.1 的文件。它還定義了所使用的編碼。大部分文件使用 UTF-8,但是,XML 設(shè)計(jì)用來集成各種語言中的數(shù)據(jù),包括那些不使用英語字母的語言。
接下來出現(xiàn)的是元素。一個(gè)元素以開始標(biāo)記開始(如 <files>),并以結(jié)束標(biāo)記結(jié)束(如 </files>),其中使用斜線 (/) 來區(qū)別于開始標(biāo)記。
元素是Node的一種類型。XML 文檔對(duì)象模型 (DOM) 定義了幾種不同的Nodes類型,包括Elements(如files或者age)、Attributes(如units)和 Text(如root或者10)。元素可以具有子節(jié)點(diǎn)。例如,age 元素有一個(gè)子元素,即文本節(jié)點(diǎn)10。而 files 元素有七個(gè)子元素。其中三個(gè)很明顯。它們分別是三個(gè)子元素:owner、action和age。其他四個(gè)分別是元素前后的空白文本符號(hào)。
XML 解析器可以利用這種父子結(jié)構(gòu)來遍歷文檔,甚至修改文檔的結(jié)構(gòu)或內(nèi)容。LibXML2 是這樣的解析器中的其中一種,并且文中的示例應(yīng)用程序正是使用這種結(jié)構(gòu)來實(shí)現(xiàn)該目的。對(duì)于各種不同的環(huán)境,有許多不同的解析器和庫。LibXML2 是用于 UNIX 環(huán)境的解析器和庫中最好的一種,并且經(jīng)過擴(kuò)展,它提供了對(duì)幾種腳本語言的支持,如 Perl 和 Python。
1 tree
/*******************************************
* compile: gcc -I/usr/include/libxml2/ -lxml2 tree1.c
* usage: create a xml tree
*
*******************************************/
#include <stdio.h>
#include <libxml/parser.h>
#include <libxml/tree.h>
int main(int argc, char **argv)
{
xmlDocPtr doc = NULL; /* document pointer */
xmlNodePtr root_node = NULL, node = NULL, node1 = NULL; /* node pointers */
//Creates a new document, a node and set it as a root node
doc = xmlNewDoc(BAD_CAST "1.0");
root_node = xmlNewNode(NULL, BAD_CAST "root");
xmlDocSetRootElement(doc, root_node);
//creates a new node, which is "attached" as child node of root_node node.
xmlNewChild(root_node, NULL, BAD_CAST "node1",BAD_CAST "content of node1");
// xmlNewProp() creates attributes, which is "attached" to an node.
node=xmlNewChild(root_node, NULL, BAD_CAST "node3", BAD_CAST"node has attributes");
xmlNewProp(node, BAD_CAST "attribute", BAD_CAST "yes");
//Here goes another way to create nodes.
node = xmlNewNode(NULL, BAD_CAST "node4");
node1 = xmlNewText(BAD_CAST"other way to create content");
xmlAddChild(node, node1);
xmlAddChild(root_node, node);
//Dumping document to stdio or file
xmlSaveFormatFileEnc(argc > 1 ? argv[1] : "-", doc, "UTF-8", 1);
/*free the document */
xmlFreeDoc(doc);
xmlCleanupParser();
xmlMemoryDump(); //debug memory for regression tests
return(0);
}
生成的xml:
[denny@localhost xml]$ gcc -I/usr/include/libxml2/ -lxml2 tree1.c
[denny@localhost xml]$ ./a.out
<?xml version="1.0" encoding="UTF-8"?>
<root>
<node1>content of node1</node1>
<node3 attribute="yes">node has attributes</node3>
<node4>other way to create content</node4>
</root>
執(zhí)行序列:
1 聲明指針:文檔指針(xmlDocPtr),結(jié)點(diǎn)指針(xmlNodePtr);
2 生成文檔doc:xmlNewDoc
3 生成根結(jié)點(diǎn)root_node: xmlNewDocNode ,xmlNewNode
4 文檔與根結(jié)點(diǎn)捆綁: xmlDocSetRootElement
5 結(jié)點(diǎn)操作
1)創(chuàng)建子結(jié)點(diǎn):xmlNewChild或xmlNewNode
2)設(shè)置結(jié)點(diǎn)屬性:xmlNewProp
3)設(shè)置結(jié)點(diǎn)值:xmlNewText,xmlNewChild, xmlAddChild
6 釋放內(nèi)存:xmlFreeDoc,xmlMemoryDump
7 lib的載入退出: LIBXML_TEST_VERSION , xmlCleanupParser
2 parse
對(duì)于應(yīng)用程序來說,讀取 XML 文件的第一步是加載該數(shù)據(jù)并將其解析為一個(gè)Document對(duì)象。在此基礎(chǔ)上,可以對(duì) DOM 樹進(jìn)行遍歷以獲取特定的節(jié)點(diǎn)。
/*******************************************
* compile: gcc -I/usr/include/libxml2/ -lxml2 tree1.c
* usage: tree2 filename_or_URL
*
*******************************************/
#include <stdio.h>
#include <libxml/parser.h>
#include <libxml/tree.h>
#ifdef LIBXML_TREE_ENABLED
static void
print_element_names(xmlNode * a_node)
{
xmlNode *cur_node = NULL;
for (cur_node = a_node; cur_node; cur_node = cur_node->next) {
if (cur_node->type == XML_ELEMENT_NODE) {
printf("node type: Element, name: %s\n", cur_node->name);
}
print_element_names(cur_node->children);
}
}
/**
* Simple example to parse a file called "file.xml",
* walk down the DOM, and print the name of the
* xml elements nodes.
*/
int
main(int argc, char **argv)
{
xmlDoc *doc = NULL;
xmlNode *root_element = NULL;
if (argc != 2)
return(1);
//LIBXML_TEST_VERSION
/*parse the file and get the DOM */
doc = xmlReadFile(argv[1], NULL, 0);
if (doc == NULL) {
printf("error: could not parse file %s\n", argv[1]);
}
/*Get the root element node */
root_element = xmlDocGetRootElement(doc);
print_element_names(root_element);
/*free the document */
xmlFreeDoc(doc);
//xmlCleanupParser();
return 0;
}
#else
int main(void) {
fprintf(stderr, "Tree support not compiled in\n");
exit(1);
}
#endif
執(zhí)行序列:
1 聲明指針:文檔指針(xmlDocPtr),結(jié)點(diǎn)指針(xmlNodePtr);
2 得到文檔doc: xmlReadFile
3 得到根結(jié)點(diǎn)root_node:xmlDocGetRootElement
4 結(jié)點(diǎn)操作:
1)獲得到結(jié)點(diǎn)值:xmlNodeGetContent(對(duì)應(yīng)于xmlFree)
2)遍歷:
指向下一個(gè)結(jié)點(diǎn):xmlNodePtr ->children
結(jié)點(diǎn)值:xmlNodePtr->name,
結(jié)點(diǎn)內(nèi)遍歷:xmlNodePtr->next
5 釋放內(nèi)存:xmlFreeDoc,xmlFree