libxml的使用(1)--读取xml http://blog.csdn.net/hdutigerkin/article/details/7546899

前端之家收集整理的这篇文章主要介绍了libxml的使用(1)--读取xml http://blog.csdn.net/hdutigerkin/article/details/7546899前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

libxml的使用(1)--读取xml

3408人阅读 评论(0) 收藏 举报

libxml是一个用于解析xml文件的库,在各个平台下都能使用,也支持多种语言,如c,python等。这里是官方网站。上面有libxml的api和一些code examples,都是英文的。不过比较简单。

libxml的基础功能就是对xml的读和写。下面将简单介绍libxml的读的功能。(大部分内容是参照libxml tutorial 的文档)


0 编译程序

因为本人是在linux下用c语言来介绍libxml的,所以使用了gcc编译器。其他的编译命令请参照官网。

我们知道,gcc 最简单的编译命令为gcc filename.c 。只要给这个命令添加文件链接库的地址就可以使用libxml。而libxml也提供了一个脚本xml2-config来配置这些地址。所以编译时将命令改为gcc filename.c `xml2-config --cflags --libs`即可。cflags在编译时提供头文件的地址,而libs在链接时提供库文件的地址。

1 分析文件--parse file

先简单介绍xml文件

<?xml version="1.0" encoding="UTF-8"?>
<root>
<node1>content1</node1>
<node2 attribute="yes">content2</node2>
<node3>
<subnode>go</subnode>
</node3>
</root>

上面是一个简单的xml文件。从文件中很容易就能看出整个文件的结构和要表达的意思。下面我会结合xml的基本类型介绍这个文件

文件的第一行是xml文件的一些属性,可以看出编码方式是utf-8 。libxml只能处理uft-8 和 utf-16编码的文件,如果你的文件不是这两种编码,需要在使用前进行转换。

<root></root>是xml的一个节点,即xmlNode。而xmlNodePtr 表示指向xmlNode的指针--xmlNode*。<node1></node1>,<node2></node2>,<node3></node3>是这个node的子node,即xmlNodePtr->children或xmlNodePtr->xmlChildrenNode。所以<subnode></subnode>就是<node3></node3>的子node。


接下来就是解析文件了。

  1. #include<stdio.h>
  2. #include<string.h>
  3. #include<stdlib.h>
  4. #include<libxml/tree.h>
  5. #include<libxml/parser.h>

文件中需要包含这两个头文件

?
    xmlDocPtrdoc=NULL;
  1. xmlNodePtrnode=NULL;
  2. doc=xmlParseFile(filename);
  3. if(NULL==doc){
  4. fprintf(stderr,"parseerror\n");
  5. exit(1);
  6. }

xmlDocPtr 表示指向xmlDoc的指针。从tutorial中我们可以知道,xmlDoc是一个包含了已解析的文件生成的节点树的结构体。

?
    node=xmlDocGetRootElement(doc);
  1. if(NULL==node){
  2. fprintf(stderr,0); background-color:inherit">"dochasnocontent\n");
?
    xmlFreeDoc(doc);
  1. }

xmlDocGetRootElement(doc)可以得到整个文件的根节点,所有的操作都是从根节点开始的。

现在我们已经有了一个包含这个节点树的结构体指针xmlDocPtr doc,有了一个可以操作节点的结构体指针xmlNodePtr node,我们就可以读取各个节点的信息了。

节点包含这么几个信息:

node->name:节点的名字,如node1,node2,subnode等

node->xmlChildrenNode:节点的子节点

node->last:节点的最后一个子节点

node->parent:节点的父节点

node->next:节点的兄弟节点,对于node1来说,node2和node3都是其兄弟节点,node1的next指向node2

由于节点的内容是其子节点(对于node1,content1可以说是其子节点),所以我们需要使用xmlNodeGetContent来取出内容

?
    node=node->xmlChildrenNode;
  1. while(node!=NULL){
  2. printf("name=%scontent=%s\n",
  3. node->name,
  4. (char*)xmlNodeGetContent(node));
  5. node=node->next;
  6. }

这是完整的源码。

?
    #include<libxml/parser.h>
  1. staticint
  2. parseDoc(char*docname){
  3. xmlDocPtrdoc;
  4. xmlNodePtrcur;
  5. //xmlKeepBlanksDefault(0);
  6. doc=xmlParseFile(docname);
  7. if(doc==NULL){
  8. "docerror!\n");
  9. return0;
  10. }
  11. cur=xmlDocGetRootElement(doc);
  12. if(cur==NULL){
  13. "rooterror!\n");
  14. xmlFreeDoc(doc);
  15. if(xmlStrcmp(cur->name,(constxmlChar*)"root")){
  16. printf("end\n");
  17. return0;
  18. }
  19. cur=cur->children;
  20. while(cur!=NULL){
  21. char*)xmlNodeGetContent(cur));
  22. //cur->content);
  23. cur=cur->next;
  24. intmain(){
  25. char*docname="story.xml";
  26. parseDoc(docname);
  27. return1;
  28. }


编译链接后执行,会发现输出的结果如下:

?
    name=textcontent=
  1. name=node1content=content1
  2. name=textcontent=
  3. name=node2content=content2
  4. name=textcontent=
  5. name=node3content=
  6. go
  7. name=textcontent=

这是因为libxml默认将各个节点间的空格当作一个节点,只要在调用xmlParseFile之前调用xmlKeepBlanksDefault(0)即可。

修改后结果如下:

?
    name=node1content=content1
  1. name=node3content=go

2 读取内存中的xml文档。

很多时候我们需要对内存中的xml文档进行操作。比如在网络编程的时候经常会从server那里接受一些客户端的配置信息,这些配置信息大部分都是使用xml语言描述的。在你将这些信息读入到buffer中后,你无需将他们写入文件当中再分析,直接可以调用xmlReadMemory函数就可以得到一个xmlDocPtr。这个函数接受五个参数,第一个参数为缓存区的指针,第二个参数为缓存区大小,其他参数具体看API文档。当然另外一个函数xmlReadDoc也能实现这样的功能

?
    staticchar*config="<config/>";
  1. xmlDocPtrdoc=NULL;
  2. xmlKeepBlanksDefault(0);
  3. doc=xmlReadMemory(config,strlen(config),0); background-color:inherit">"in_memory.xml",NULL,0);
  4. //handledoc
  5. xmlFreeDoc(doc);

猜你在找的XML相关文章