libxml(一)
摘要 Libxml是一个有免费许可的用于处理XML、可以轻松跨越多个平台的C语言库。这个指南提供它的基本函数的例子。 绪论 Libxml 是一个实现读、创建及操纵XML数据功能的C语言库。这个指南提供例子代码并给出它基本功能的解释。在这个项目的主页上有Libxml及更多关于它可用的 资料。包含有完整的API文档。这个指南并不能替代这些完整的文档,但是阐明功能需要使用库来完成基本操作。 这个指南基于一个简单的XML应用,它使用我写的一篇文章生成,它包含有元数据和文章的主体。 本指南中的例子代码示范如何做到:
• 解析文档 • 取得指定元素的文本 • 添加一个元素及它的内容 • 添加一个属性 • 取得一个属性的值 例子的完整代码包含在附录中 数据类型 解析文档 ①xmlDocPtr doc; 注释 取得元素内容 你找到在文档树中你要查找的元素后可以取得它的内容。在这个例子中我们查找“story”元素。进程将在冗长的树中查找我们感兴趣的元素。我们假定期你已经有了一个名为doc的xmlDocPtr和一个名为cur的xmlNodPtr。 void 使用XPath取得元素内容 注释 function.
The function returns an xmlXPathObjectPtr, which includes the set of nodes satisfying the XPath expression. 使用XPath需要安装xmlXPathContext才支持XPath表达式及xmlXPathEvalExpression函数,这个函数返回一个xmlXPathObjectPtr,它包含有 XPath表达式的结点集。
xmlXPathObjectPtr ①for (i=0; i < nodeset->nodeNr; i++) { 写元素
写元素内容使用上面许多一样的步骤—解析文档并遍历树。我们先解析文档然后遍历树查找我们想插入元素的位置。在这个例子中,我们再一次查找“storyinfo ”元素并插入一个keyword。然后我们装文件写入磁盘。完整代码:附录E,添加keyword例程
本例中主要的不同在于parseStory void parseStory (xmlDocPtr doc, xmlNodePtr cur, char *keyword) { ①xmlNewTextChild (cur, NULL, "keyword", keyword); return; } ①XmlNewTextChild函数添加一个当前结点的新的子元素到树中 一旦结点被添加,我们应当写文档到文件中。你是否想给元素指定一个命名空间?你能添加它,在我们的例子中,命名空间是NULL。 xmlSaveFormatFile (docname, doc, 1); 第一个参数是写入文件的名,你注意到和我们刚刚读入的文件名是一样的。在这个例子中,我们仅仅覆盖原来的文件。第二个参数是一个xmlDoc结构指针,第三个参数设定为1,保证在输出上写入。 写属性 xmlAttrPtr newattr; 我们也需要xmlNodePtr: xmlNodePtr newnode; 剩下的parseDoc则和前面一样,检查根结点是否为story。如果是的,那我们知道我们将在指定的位置添加我们的元素。 取得属性 这个例子的初始步骤和前面是类似的:解析文档,查找你感兴趣的元素,然后进入一个函数完成指定的请求任务。在这个例子中,我们调用getReference。
void 注释 编码转换 稍后的讨论来思考设计你的应用程序将帮助你避免这个困难。实际上,libxml能以UTF-8格式保存和操纵多种数据
你的程序使用其它的数据格式,比如常见的ISO-8859-1编码,必须使用libxml函数转换到UTF-8。如果你想你的程序以除UTF-8外的其它编码方式输出也必须做转换。 如 果能有效地转换数据Libxml将使用转换器。无转换器时,仅仅UTF-8、UTF-16和ISO-8859-1能够被作为外部格式使用。有转换器时,它 能将从其它格式与UTF-8互换的任何格式均可使用。当前转换器支持大约150种不同的编码格式之间的相互转换。实际支持的格式数量正在被实现。每一个实 现在的转换器尽可能的支持每一种格式。 警告 包含在例子中的转换函数使用libxml的xmlFindCharEncodingHandler函数。 ①xmlCharEncodingHandlerPtr handler; A. 编译 为了取得预处理和编译标志,使用xml2-config –cflags,为了取得链接标志,使用xml2-config –libs。其它有效的参数请使用xml2-config –help查阅。
B. 示例文档 libxml(三)
D. XPath例程代码 #include <libxml/parser.h> #include <libxml/xpath.h> xmlDocPtr getdoc (char *docname) { xmlDocPtr doc; doc = xmlParseFile(docname); if (doc == NULL ) { fprintf(stderr,"Document not parsed successfully. /n"); return NULL; } return doc; } xmlXPathObjectPtr getnodeset (xmlDocPtr doc, xmlChar *xpath){ xmlXPathContextPtr context; xmlXPathObjectPtr result; context = xmlXPathNewContext(doc); result = xmlXPathEvalExpression(xpath, context); if(xmlXPathNodeSetIsEmpty(result->nodesetval)){ printf("No result/n"); return NULL; } xmlXPathFreeContext(context); return result; } int main(int argc, char **argv) { char *docname; xmlDocPtr doc; xmlChar *xpath = ("//keyword"); xmlNodeSetPtr nodeset; xmlXPathObjectPtr result; int i; xmlChar *keyword; if (argc <= 1) { printf("Usage: %s docname/n", argv[0]); return(0); } docname = argv[1]; doc = getdoc(docname); result = getnodeset (doc, xpath); if (result) { nodeset = result->nodesetval; for (i=0; i < nodeset->nodeNr; i++) { keyword = xmlNodeListGetString(doc, nodeset->nodeTab[i]->printf ("keyword: %s/n", keyword);
xmlFree(keyword); } xmlXPathFreeObject (result); } xmlFreeDoc(doc); xmlCleanupParser(); return (1); } E. 添加keyword例程代码 #include <stdio.h> #include <string.h> #include <stdlib.h> #include <libxml/xmlmemory.h> #include <libxml/parser.h> void parseStory (xmlDocPtr doc, xmlNodePtr cur, char *keyword) { xmlNewTextChild (cur, NULL, "keyword", keyword); return; } xmlDocPtr parseDoc(char *docname, char *keyword) { xmlDocPtr doc; xmlNodePtr cur; doc = xmlParseFile(docname); if (doc == NULL ) { fprintf(stderr,"Document not parsed successfully. /n"); return (NULL); } cur = xmlDocGetRootElement(doc); if (cur == NULL) { fprintf(stderr,"empty document/n"); xmlFreeDoc(doc); return (NULL); } if (xmlStrcmp(cur->name, (const xmlChar *) "story")) { fprintf(stderr,"document of the wrong type, root node != story"); xmlFreeDoc(doc); return (NULL); } cur = cur->xmlChildrenNode; while (cur != NULL) { if ((!xmlStrcmp(cur->name, (const xmlChar *)"storyinfo"))){ parseStory (doc, cur, keyword); } cur = cur->next; } return(doc); } int main(int argc, char **argv) { char *docname; char *keyword; xmlDocPtr doc; if (argc <= 2) { printf("Usage: %s docname, keyword/n", argv[0]); return(0); } docname = argv[1]; keyword = argv[2]; doc = parseDoc (docname, keyword); if (doc != NULL) { xmlSaveFormatFile (docname, doc, 0); xmlFreeDoc(doc); } return (1); } F. 添加属性例程代码 #include <stdio.h> #include <string.h> #include <stdlib.h> #include <libxml/xmlmemory.h> #include <libxml/parser.h> xmlDocPtr parseDoc(char *docname, char *uri) { xmlDocPtr doc; xmlNodePtr cur; xmlNodePtr newnode; xmlAttrPtr newattr; doc = xmlParseFile(docname); if (doc == NULL ) { fprintf(stderr,"Document not parsed successfully. /n"); return (NULL); } cur = xmlDocGetRootElement(doc); if (cur == NULL) { fprintf(stderr,"empty document/n"); xmlFreeDoc(doc); return (NULL); } if (xmlStrcmp(cur->name, (const xmlChar *) "story")) { fprintf(stderr,"document of the wrong type, root node != story"); xmlFreeDoc(doc); return (NULL); } newnode = xmlNewTextChild (cur, NULL, "reference", NULL); newattr = xmlNewProp (newnode, "uri", uri); return(doc); } int main(int argc, char **argv) { char *docname; char *uri; xmlDocPtr doc; if (argc <= 2) { printf("Usage: %s docname, uri/n", argv[0]); return(0); } docname = argv[1]; uri = argv[2]; doc = parseDoc (docname, uri); if (doc != NULL) { xmlSaveFormatFile (docname, doc, 1); xmlFreeDoc(doc); } return (1); } G. 取得属性值例程代码 #include <stdio.h> #include <string.h> #include <stdlib.h> #include <libxml/xmlmemory.h> #include <libxml/parser.h> void getReference (xmlDocPtr doc, xmlNodePtr cur) { xmlChar *uri; cur = cur->xmlChildrenNode; while (cur != NULL) { if ((!xmlStrcmp(cur->name, (const xmlChar *)"reference"))) { uri = xmlGetProp(cur, "uri"); printf("uri: %s/n", uri); xmlFree(uri); } cur = cur->next; } return; } void parseDoc(char *docname) { xmlDocPtr doc; xmlNodePtr cur; doc = xmlParseFile(docname); if (doc == NULL ) { fprintf(stderr,"Document not parsed successfully. /n"); return; } cur = xmlDocGetRootElement(doc); if (cur == NULL) { fprintf(stderr,"empty document/n"); xmlFreeDoc(doc); return; } if (xmlStrcmp(cur->name, (const xmlChar *) "story")) { fprintf(stderr,"document of the wrong type, root node != story"); xmlFreeDoc(doc); return; } getReference (doc, cur); xmlFreeDoc(doc); return; } int main(int argc, char **argv) { char *docname; if (argc <= 1) { printf("Usage: %s docname/n", argv[0]); return(0); } docname = argv[1]; parseDoc (docname); return (1); } H. 编码转换例程代码 #include <string.h> #include <libxml/parser.h> unsigned char* convert (unsigned char *in, char *encoding) { unsigned char *out; int ret,size,out_size,temp; xmlCharEncodingHandlerPtr handler; size = (int)strlen(in)+1; out_size = size*2-1; out = malloc((size_t)out_size); if (out) { handler = xmlFindCharEncodingHandler(encoding); if (!handler) { free(out); out = NULL; } } if (out) { temp=size-1; ret = handler->input(out, &out_size, in, &temp); if (ret || temp-size+1) { if (ret) { printf("conversion wasn't successful./n"); } else { printf("conversion wasn't successful. converted: } free(out); out = NULL; } else { out = realloc(out,out_size+1); out[out_size]=0; /*null terminating out*/ } } else { printf("no mem/n"); } return (out); } int main(int argc, char **argv) { unsigned char *content, *out; xmlDocPtr doc; xmlNodePtr rootnode; char *encoding = "ISO-8859-1"; if (argc <= 1) { printf("Usage: %s content/n", argv[0]); return(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); return (1); } ………………………………………………………………………………………… char *convert(char *instr,char *encoding)
{ xmlCharEncodingHandlerPtr handler; xmlBufferPtr in,out; handler = xmlFindCharEncodingHandler(encoding);
if(NULL != handler) { in = xmlBufferCreate(); xmlBufferWriteChar(in,instr); out = xmlBufferCreate(); if(xmlCharEncInFunc(handler, out, in) 〈 0) { xmlBufferFree(in); xmlBufferFree(out); return NULL; } else { xmlBufferFree(in); return (char *)out-〉content; } } } |