绪论
Libxml是个有免费许可用于处理XML、可以轻松跨越多个平台C语言库Libxml实现了读、创建及操纵XML数据功能
这个指南基于个简单XML应用
数据类型
Libxml 定义了许多数据类型它隐藏了杂乱来源以致你不必处理它除非你有特定需要xmlChar 替代char,使用UTF-8编码字节串如果你数据使用其它编码它必须被转换到UTF-8才能使用libxml在libxml编码支持WEB页面有更多有关编码有用信息
XmlDoc 包含由解析文档建立树结构xmlDocPtr是指向这个结构指针
xmlNodePtr and xmlNode 包含单结点结构xmlNodePtr是指向这个结构指针它被用于遍历文档树
解析文档
解析文档时仅仅需要文件名并只个并有检查
①xmlDocPtr doc;
②xmlNodePtr cur;
③doc = xmlParseFile(docname);
④ (doc NULL ) {
fprf(stderr,\"Document not parsed successfully. \\n\");
;
}
⑤cur = xmlDocGetRootElement(doc);
⑥ (cur NULL) {
fprf(stderr,\"empty document\\n\");
xmlFreeDoc(doc);
;
}
⑦ (xmlStrcmp(cur->name, (const xmlChar *) \"story\")) {
fprf(stderr,\"document of the wrong type, root node != story\");
xmlFreeDoc(doc);
;
}
①定义解析文档指针
②定义结点指针(需要它为了在各个结点间移动)
④检查解析文档是否成功如果不成功libxml将指个注册并停止
注释
个常见是不适当编码XML标准文档除了用UTF-8或UTF-16外还可用其它编码保存如果文档是这样libxml将自动地为你转换到UTF-8
⑤取得文档根元素
⑥检查确认当前文档中包含内容
⑦在这个例子中我们需要确认文档是正确类型“Story”是在这个指南中使用文档根类型
取得元素内容
找到在文档树中要查找元素后可以取得它内容在这个例子中我们查找“story”元素进程将在冗长树中查找我们感兴趣元素我们假定期你已经有了个名为docxmlDocPtr和个名为curxmlNodPtr
①cur = cur->xmlChildrenNode;
②while (cur != NULL) {
((!xmlStrcmp(cur->name, (const xmlChar *)\"storyinfo\"))){
parseStory (doc, cur);
}
cur = cur->next;
}
①取得cur第个子结点cur指向文档根即“story”元素
②这个循环迭代通过“story”子元素查找“storyinfo”这是个包含有我们将查找“keywords”元素它使用了libxml串比较xmlStrcmp如果相符它parseStory
void parseStory (xmlDocPtr doc, xmlNodePtr cur) {
xmlChar *key;
① cur = cur->xmlChildrenNode;
②while (cur != NULL) {
((!xmlStrcmp(cur->name, (const xmlChar *)\"keyword\"))) {
③ key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
prf(\"keyword: %s\\n\", key);
xmlFree(key);
}
cur = cur->next;
}
;
}
①再次取得第个子结点
②像上面那个循环样我们能过迭代查找我们感兴趣叫做“keyword”元素
③当我们找到元素“keyword”时我们需要打印它包含在XML中记录内容文本被包含于元素子结点中因此我们借助了cur-> xmlChildrenNode为了取得文本我们使用xmlNodeListGetString它有个文档指针参数在这个例 子中我们仅仅打印它
注释
xmlNodeListGetString为它返回串分配内存你必须使用xmlFree释放它
使用XPath取得元素内容
除了步步遍历文档树查找元素外Libxml2包含支持使用Xpath表达式取得指定结点集完整Xpath API文档在这里Xpath允许通过路径文档搜索匹配指定条件结点在下面例子中我们搜索文档中所有“keyword”元素
注释
下面是Xpath完整讨论它详细使用资料请查阅Xpath规范标准
这个例子完整代码参见附录DXPath例程代码
Using XPath requires ting up an xmlXPathContext and then supplying the XPath expression and the context to the xmlXPathEvalExpression
[Page]function.
The function s an xmlXPathObjectPtr, which s the of nodes satisfying the XPath expression.
使用XPath需要安装xmlXPathContext才支持XPath表达式及xmlXPathEvalExpression这个返回个xmlXPathObjectPtr它包含有
XPath表达式结点集
xmlXPathObjectPtr
getnode (xmlDocPtr doc, xmlChar *xpath){
①xmlXPathContextPtr context;
xmlXPathObjectPtr result;
②context = xmlXPathNewContext(doc);
③result = xmlXPathEvalExpression(xpath, context);
④(xmlXPathNodeSetIsEmpty(result->nodeval)){
prf(\"No result\\n\");
NULL;
}
xmlXPathFreeContext(context);
result;
}
①首先定义变量
②化变量context
③应用XPath表达式
④检查结果
由返回xmlPathObjectPtr包含个结点集和其它需要被迭代及操作信息在这个例子中我们返回 xmlXPathObjectPtr我们使用它打印我们文档中keyword结点内容这个结点集对象包含在集合(nodeNr)中元素数目及个结点(nodeTab)
①for (i=0; i < node->nodeNr; i) {
②keyword = xmlNodeListGetString(doc,
node->nodeTab[i]->xmlChildrenNode, prf(\"keyword: %s\\n\", keyword);
xmlFree(keyword);
}
①变量node->Nr持有结点集中元素数量我们使用它遍历
②打印每个结点包含内容
注释
Note that we are pring the child node of the node that is ed, because the contents of the keyword element are a child text node.注意我们打印是结点子结点返回值keyword元素内容是个子文本结点
写元素
写元素内容使用上面许多样步骤—解析文档并遍历树我们先解析文档然后遍历树查找我们想插入元素位置在这个例子中我们再次查找“storyinfo
”元素并插入个keyword然后我们装文件写入磁盘完整代码:附录E添加keyword例程
本例中主要区别在于parseStory
void
parseStory (xmlDocPtr doc, xmlNodePtr cur, char *keyword) {
①xmlNewTextChild (cur, NULL, \"keyword\", keyword);
;
}
①XmlNewTextChild添加个当前结点新子元素到树中
旦结点被添加我们应当写文档到文件中你是否想给元素指定个命名空间?你能添加它在我们例子中命名空间是NULL
xmlSaveFormatFile (docname, doc, 1);
第个参数是写入文件名你注意到和我们刚刚读入文件名是样在这个例子中我们仅仅覆盖原来文件第 2个参数是个xmlDoc结构指针第 3个参数设定为1保证在输出上写入
写属性
写属性类似于给个新元素写文本在这个例子中我们将添加个reference结点URI属性到我们文档中reference是story元素个子结点所以找到并插入新元素及其属性是简单旦我们在parseDoc进行了检查我们将在正确位置加放我们新元素但进行的前我们需要定义个此前我们不见过数据类型
xmlAttrPtr attr;
我们也需要xmlNodePtr:
xmlNodePtr node;
剩下parseDoc则和前面样检查根结点是否为story如果是那我们知道我们将在指定位置添加我们元素
① node = xmlNewTextChild (cur, NULL, \"reference\", NULL);
②attr = xmlNewProp (node, \"uri\", uri);
①使用xmlNewTextChild添国个新结点到当前结点位置
旦结点被添加文件应像前面例子将我们添加元素及文本内容写入磁盘
取得属性
取得属性值类似于前面我们取得个结点文本内容在这个例子中我们将取出我们在前部分添加URI值
[Page]
这个例子步骤和前面是类似:解析文档查找你感兴趣元素然后进入个完成指定请求任务在这个例子中我们getReference
void
getReference (xmlDocPtr doc, xmlNodePtr cur) {
xmlChar *uri;
cur = cur->xmlChildrenNode;
while (cur != NULL) {
((!xmlStrcmp(cur->name, (const xmlChar *)\"reference\"))) {
① uri = xmlGetProp(cur, \"uri\");
prf(\"uri: %s\\n\", uri);
xmlFree(uri);
}
cur = cur->next;
}
;
}
①关键是xmlGetProp,它返回个包含属性值xmlChar在本例中我们仅仅打印它
注释
如果你使用DTD定义属性固定值或缺省值这个也将取得它
编码转换
数据编码兼容问题是员新建普通XML或特定XML时最常见困难按照这里
稍后讨论来研究设计你应用将帮助你避免这个困难实际上libxml能以UTF-8格式保存和操纵多种数据
你使用其它数据格式比如常见ISO-8859-1编码必须使用libxml转换到UTF-8如果你想你以除UTF-8外其它编码方式输出也必须做转换
如果能有效地转换数据Libxml将使用转换器无转换器时仅仅UTF-8、UTF-16和ISO-8859-1能够被作为外部格式使用有转换器时它能将从其它格式和UTF-8互换任何格式均可使用当前转换器支持大约150种区别编码格式的间相互转换实际支持格式数量正在被实现每个实现在转换器尽可能支持每种格式
警告
个常见是在内部数据区别部分使用区别编码格式最常见是情况是个应用以ISO-8859-1作为内部数据格式结合libxml部分使用UTF-8格式结果是个应用要面对区别地内部数据格式部分代码执行后它或其它部分代码将使用曲解数据
这个例子构造个简单文档然后添加在命令行提供内容到根元素并使用适当编码将结果输出到标准输出设备上在这个例子中我们使用ISO-8859 -1编码在命令输入内容将被从ISO-8859-1
转换到UTF-8
包含在例子中转换使用libxmlxmlFindCharEncodingHandler
①xmlCharEncodingHandlerPtr handler;
②size = ()strlen(in)+1;
out_size = size*2-1;
out = malloc((size_t)out_size);
…
③handler = xmlFindCharEncodingHandler(encoding);
…
④handler->input(out, &out_size, in, &temp);
…
⑤xmlSaveFormatFileEnc(\"-\", doc, encoding, 1);
①定义个xmlCharEncodingHandler指针
②XmlCharEncodingHandler需要给出输入和输出串大小这里计算输入输出串
③XmlFindCharEncodingHandler使用数据编码作为参数搜索libxml已经完成转换器句柄并将找到指针返回如果没有找到则返回NULL
④The conversion function identied by handler requires as its arguments poers to the input and output s, along with the length of each. The lengths must be determined separately by the application.
由句柄指定转换请求输入、输出中及它们长度作为参数这个长度必须由应用分别指定
⑤用指定编码而不是UTF-8输出我们使用xmlSaveFormatFileEnc指不定期编码方式
A. 编译
Libxml包含个脚本xml2-config它般用于编译和链接到库时产生标志
[Page]为了取得预处理和编译标志使用xml2-config –cflags为了取得链接标志使用xml2-config –libs其它有效参数请使用xml2-config –help查阅
B. 举例文档
<?xml version=\"1.0\"?>
<story>
<storyinfo>
<author>John Fleck</author>
<datewritten>June 2, 2002</datewritten>
<keyword>example keyword</keyword>
</storyinfo>
<body>
<headline>This is the headline</headline>
<para>This is the body text.</para>
</body>
</story>
C. Keyword例程代码
# <stdio.h>
# <.h>
# <stdlib.h>
# <libxml/xmlmemory.h>
# <libxml/parser.h>
void
parseStory (xmlDocPtr doc, xmlNodePtr cur) {
xmlChar *key;
cur = cur->xmlChildrenNode;
while (cur != NULL) {
((!xmlStrcmp(cur->name, (const xmlChar *)\"keyword\"))) {
key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
prf(\"keyword: %s\\n\", key);
xmlFree(key);
}
cur = cur->next;
}
;
}
void
parseDoc(char *docname) {
xmlDocPtr doc;
xmlNodePtr cur;
doc = xmlParseFile(docname);
(doc NULL ) {
fprf(stderr,\"Document not parsed successfully. \\n\");
;
}
cur = xmlDocGetRootElement(doc);
(cur NULL) {
fprf(stderr,\"empty document\\n\");
xmlFreeDoc(doc);
;
}
(xmlStrcmp(cur->name, (const xmlChar *) \"story\")) {
fprf(stderr,\"document of the wrong type, root node != story\");
xmlFreeDoc(doc);
;
}
cur = cur->xmlChildrenNode;
while (cur != NULL) {
((!xmlStrcmp(cur->name, (const xmlChar *)\"storyinfo\"))){
parseStory (doc, cur);
}
cur = cur->next;
}
xmlFreeDoc(doc);
;
}
( argc, char **argv) {
char *docname;
(argc <= 1) {
prf(\"Usage: %s docname\\n\", argv[0]);
(0);
}
docname = argv[1];
parseDoc (docname);
(1);
}
libxml( 3)
D. XPath例程代码
# <libxml/parser.h>
# <libxml/xpath.h>
xmlDocPtr
getdoc (char *docname) {
xmlDocPtr doc;
doc = xmlParseFile(docname);
(doc NULL ) {
fprf(stderr,\"Document not parsed successfully. \\n\");
NULL;
}
doc;
}
xmlXPathObjectPtr
getnode (xmlDocPtr doc, xmlChar *xpath){
xmlXPathContextPtr context;
xmlXPathObjectPtr result;
context = xmlXPathNewContext(doc);
result = xmlXPathEvalExpression(xpath, context);
(xmlXPathNodeSetIsEmpty(result->nodeval)){
prf(\"No result\\n\");
NULL;
}
xmlXPathFreeContext(context);
result;
}
( argc, char **argv) {
char *docname;
xmlDocPtr doc;
xmlChar *xpath = (\"//keyword\");
xmlNodeSetPtr node;
xmlXPathObjectPtr result;
i;
xmlChar *keyword;
(argc <= 1) {
prf(\"Usage: %s docname\\n\", argv[0]);
(0);
}
docname = argv[1];
doc = getdoc(docname);
result = getnode (doc, xpath);
(result) {
node = result->nodeval;
for (i=0; i < node->nodeNr; i) {
keyword = xmlNodeListGetString(doc, node->nodeTab[i]->prf
[Page](\"keyword: %s\\n\", keyword);
xmlFree(keyword);
}
xmlXPathFreeObject (result);
}
xmlFreeDoc(doc);
xmlCleanupParser;
(1);
}
E. 添加keyword例程代码
# <stdio.h>
# <.h>
# <stdlib.h>
# <libxml/xmlmemory.h>
# <libxml/parser.h>
void
parseStory (xmlDocPtr doc, xmlNodePtr cur, char *keyword) {
xmlNewTextChild (cur, NULL, \"keyword\", keyword);
;
}
xmlDocPtr
parseDoc(char *docname, char *keyword) {
xmlDocPtr doc;
xmlNodePtr cur;
doc = xmlParseFile(docname);
(doc NULL ) {
fprf(stderr,\"Document not parsed successfully. \\n\");
(NULL);
}
cur = xmlDocGetRootElement(doc);
(cur NULL) {
fprf(stderr,\"empty document\\n\");
xmlFreeDoc(doc);
(NULL);
}
(xmlStrcmp(cur->name, (const xmlChar *) \"story\")) {
fprf(stderr,\"document of the wrong type, root node != story\");
xmlFreeDoc(doc);
(NULL);
}
cur = cur->xmlChildrenNode;
while (cur != NULL) {
((!xmlStrcmp(cur->name, (const xmlChar *)\"storyinfo\"))){
parseStory (doc, cur, keyword);
}
cur = cur->next;
}
(doc);
}
( argc, char **argv) {
char *docname;
char *keyword;
xmlDocPtr doc;
(argc <= 2) {
prf(\"Usage: %s docname, keyword\\n\", argv[0]);
(0);
}
docname = argv[1];
keyword = argv[2];
doc = parseDoc (docname, keyword);
(doc != NULL) {
xmlSaveFormatFile (docname, doc, 0);
xmlFreeDoc(doc);
}
(1);
}
F. 添加属性例程代码
# <stdio.h>
# <.h>
# <stdlib.h>
# <libxml/xmlmemory.h>
# <libxml/parser.h>
xmlDocPtr
parseDoc(char *docname, char *uri) {
xmlDocPtr doc;
xmlNodePtr cur;
xmlNodePtr node;
xmlAttrPtr attr;
doc = xmlParseFile(docname);
(doc NULL ) {
fprf(stderr,\"Document not parsed successfully. \\n\");
(NULL);
}
cur = xmlDocGetRootElement(doc);
(cur NULL) {
fprf(stderr,\"empty document\\n\");
xmlFreeDoc(doc);
(NULL);
}
(xmlStrcmp(cur->name, (const xmlChar *) \"story\")) {
fprf(stderr,\"document of the wrong type, root node != story\");
xmlFreeDoc(doc);
(NULL);
}
node = xmlNewTextChild (cur, NULL, \"reference\", NULL);
attr = xmlNewProp (node, \"uri\", uri);
(doc);
}
( argc, char **argv) {
char *docname;
char *uri;
xmlDocPtr doc;
(argc <= 2) {
prf(\"Usage: %s docname, uri\\n\", argv[0]);
(0);
}
docname = argv[1];
uri = argv[2];
doc = parseDoc (docname, uri);
(doc != NULL) {
xmlSaveFormatFile (docname, doc, 1);
xmlFreeDoc(doc);
}
(1);
}
G. 取得属性值例程代码
# <stdio.h>
# <.h>
# <stdlib.h>
# <libxml/xmlmemory.h>
# <libxml/parser.h>
void
getReference (xmlDocPtr doc, xmlNodePtr cur) {
xmlChar *uri;
cur = cur->xmlChildrenNode;
while (cur != NULL) {
((!xmlStrcmp(cur->name, (const xmlChar *)\"reference\"))) {
uri = xmlGetProp(cur, \"uri\");
prf(\"uri: %s\\n\", uri);
xmlFree(uri);
}
cur = cur->next;
}
;
}
void
parseDoc(char *docname) {
xmlDocPtr doc;
xmlNodePtr cur;
doc = xmlParseFile(docname);
(doc NULL ) {
fprf(stderr,\"Document not parsed successfully. \\n\");
;
}
cur = xmlDocGetRootElement(doc);
(cur NULL) {
fprf(stderr,\"empty document\\n\");
xmlFreeDoc(doc);
;
}
(xmlStrcmp(cur->name, (const xmlChar *) \"story\")) {
fprf(stderr,\"document of the wrong type, root node != story\");
xmlFreeDoc(doc);
;
}
getReference (doc, cur);
xmlFreeDoc(doc);
;
}
( argc, char **argv) {
char *docname;
(argc <= 1) {
prf(\"Usage: %s docname\\n\", argv[0]);
(0);
}
docname = argv[1];
parseDoc (docname);
(1);
}
H. 编码转换例程代码
# <.h>
# <libxml/parser.h>
unsigned char*
convert (unsigned char *in, char *encoding)
{
unsigned char *out;
ret,size,out_size,temp;
xmlCharEncodingHandlerPtr handler;
size = ()strlen(in)+1;
out_size = size*2-1;
out = malloc((size_t)out_size);
(out) {
handler = xmlFindCharEncodingHandler(encoding);
(!handler) {
free(out);
out = NULL;
}
}
(out) {
temp=size-1;
ret = handler->input(out, &out_size, in, &temp);
(ret || temp-size+1) {
(ret) {
prf(\"conversion wasn\'t successful.\\n\");
} {
prf(\"conversion wasn\'t successful. converted: }
free(out);
out = NULL;
} {
out = realloc(out,out_size+1);
out[out_size]=0; /*null terminating out*/
}
} {
prf(\"no mem\\n\");
}
(out);
}
( argc, char **argv) {
unsigned char *content, *out;
xmlDocPtr doc;
xmlNodePtr rootnode;
char *encoding = \"ISO-8859-1\";
(argc <= 1) {
prf(\"Usage: %s content\\n\", argv[0]);
(0);
}
content = argv[1];
out = convert(content, encoding);
doc = xmlNewDoc (\"1.0\");
rootnode = xmlNewDocNode(doc, NULL, (const xmlChar*)\"root\", out);
xmlDocSetRootElement(doc, rootnode);
xmlSaveFormatFileEnc(\"-\", doc, encoding, 1);
(1);
}
…………………………………………………………………………………………
[Page]char *convert(char *instr,char *encoding)
{
xmlCharEncodingHandlerPtr handler;
xmlBufferPtr in,out;
handler = xmlFindCharEncodingHandler(encoding);
(NULL != handler)
{
in = xmlBufferCreate;
xmlBufferWriteChar(in,instr);
out = xmlBufferCreate;
(xmlCharEncInFunc(handler, out, in) 〈 0)
{
xmlBufferFree(in);
xmlBufferFree(out);
NULL;
}
{
xmlBufferFree(in);
(char *)out-〉content;
}
}
}
最新评论