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

转载 2015年07月09日 12:01:30

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>  

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

  1. xmlDocPtr doc = NULL;  
  2. xmlNodePtr node = NULL;  
  3.   
  4. doc = xmlParseFile(filename);  
  5.   
  6. if(NULL  == doc) {  
  7.     fprintf(stderr, "parse error\n");  
  8.     exit(1);  
  9. }  

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

  1. node = xmlDocGetRootElement(doc);  
  2.   
  3. if(NULL == node) {  
  4.     fprintf(stderr, "doc has no content\n");  
  1.     xmlFreeDoc(doc);  
  2.     exit(1);  
  3. }  

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来取出内容。

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

这是完整的源码。

  1. #include <stdio.h>  
  2. #include <string.h>  
  3. #include <stdlib.h>  
  4. #include <libxml/parser.h>  
  5.   
  6. static int  
  7. parseDoc(char* docname) {  
  8.     xmlDocPtr doc;  
  9.     xmlNodePtr cur;  
  10.     //xmlKeepBlanksDefault(0);  
  11.   
  12.     doc = xmlParseFile(docname);  
  13.   
  14.     if(doc == NULL) {  
  15.         fprintf(stderr, "doc error!\n");  
  16.         return 0;  
  17.     }  
  18.   
  19.     cur = xmlDocGetRootElement(doc);  
  20.   
  21.     if(cur == NULL) {  
  22.         fprintf(stderr, "root error!\n");  
  23.         xmlFreeDoc(doc);  
  24.         return 0;  
  25.     }  
  26.   
  27.     if(xmlStrcmp(cur->name, (const xmlChar*)"root")) {  
  28.         printf("end\n");  
  29.         return 0;  
  30.     }  
  31.   
  32.     cur = cur->children;  
  33.     while(cur != NULL) {  
  34.         printf("name=%s content=%s\n",cur->name,   
  35.                 (char*)xmlNodeGetContent(cur));  
  36.                 //cur->content);  
  37.         cur = cur->next;  
  38.     }  
  39.     xmlFreeDoc(doc);  
  40.     return 0;  
  41. }  
  42.   
  43. int main() {  
  44.     char* docname = "story.xml";  
  45.     parseDoc(docname);  
  46.     return 1;  
  47. }  


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

  1. name=text content=  
  2.       
  3. name=node1 content=content1  
  4. name=text content=  
  5.       
  6. name=node2 content=content2  
  7. name=text content=  
  8.       
  9. name=node3 content=  
  10.         go  
  11.       
  12. name=text content=  

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

修改后结果如下:

  1. name=node1 content=content1  
  2. name=node2 content=content2  
  3. name=node3 content=go  

2 读取内存中的xml文档。

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

  1. static char* config = "<config />";  
  2. xmlDocPtr doc = NULL;  
  3. xmlKeepBlanksDefault(0);  
  4.   
  5. doc = xmlReadMemory(config, strlen(config), "in_memory.xml", NULL, 0);  
  6.   
  7. //handle doc  
  8.   
  9. xmlFreeDoc(doc);  
  10. 在上一篇文章当中,我读取了各个节点的名字和内容,现在我将读取各个节点的属性。

    1. <?xml version="1.0" encoding="UTF-8"?>  
    2. <root>  
    3. <node1>content1</node1>  
    4. <node2 attribute="yes">content2</node2>  
    5. <node3>  
    6. <subnode>go</subnode>  
    7. </node3>  
    8. </root>  

    在node2这个节点上有一个属性attribute,其值是yes。我们可以使用xmlGetProp这个函数将其提取出来。这个函数包含了两个变量,一个是将要提取属性的节点指针xmlNodePtr,另一个是属性的名称。

    1. xmlChar* attr_value = NULL;  
    2. if(!xmlStrcmp(node->name, (const xmlChar*)"node2")) {  
    3.     attr_value = xmlGetProp(node, "attribute");  
    4.     printf("attribute value:%s\n",attr_value);  
    5.     xmlFree(attr_value);  
    6. }  
    这样我们就提取出了yes这个字符串了!

[libxml2]_[C/C++]_[高效读取XML大文件]

场景1.一个比较大的XML文件, 要读进内存里,并转换为相应的对象(比如一个C++对象), 通常都是把整个XML文件读入转换为DOM对象, 之后对DOM对象进行枚举分析生成C++对象.2.如果这个庞大...
  • infoworld
  • infoworld
  • 2017年11月19日 21:49
  • 561

libxml2库 读取xml文件,写xml文件

所用xml文件内容: .mp3 .mp4 .wma .mkv .avi -2852 XmlReader.h实现功能,得到一个xml...
  • peng825223208
  • peng825223208
  • 2016年08月30日 14:12
  • 1409

linux下,纯c++使用libxml2读取xml文件

linux下,纯c++使用libxml2读取xml文件 下载libxml2 [url]ftp://ftp.xmlsoft.org/libxml2/libxml2-sources-2.7.1.tar...
  • wwang196988
  • wwang196988
  • 2012年04月24日 10:22
  • 1284

[libxml2]_[C/C++]_[使用libxml2读取分析xml文件]

场景: 1. xml文件大部分时候都是用来做配置用的, 而windows的msxml库又不是Windows自带的库,使用它得打包, 而且花时间学习这个独立于平台的库不划算. 2. libxml2是跨平...
  • infoworld
  • infoworld
  • 2015年07月20日 09:57
  • 2028

libxml2编程--C语言xml初使用(1)

1、下载与安装LIBXML2 Libxml2是一个C语言的XML程序库,可以简单方便的提供对XML文档的各种操作,并且支持XPATH查询,以及部分的支持XSLT转换等功能。Libxml2的下载地址是...
  • allen_ydc
  • allen_ydc
  • 2015年10月09日 16:36
  • 1338

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

转自: http://blog.csdn.net/hdutigerkin/article/details/7546899  libxml是一个用于解析xml文件的库,在各个平台...
  • u011595231
  • u011595231
  • 2013年09月26日 17:20
  • 588

XML文件的解析--非常详细的libxml库函数解释说明并附带实例

libxml(一)   摘要  Libxml是个有免费许可的用于处理XML、能轻松跨越多个平台的C语言库。这个指南提供他的基本函数的例子。 绪论  Libxml是个实现读...
  • shanzhizi
  • shanzhizi
  • 2012年07月05日 14:29
  • 3502

libxml2解析xml总结

欢迎使用Markdown编辑器写博客本Markdown编辑器使用StackEdit修改而来,用它写博客,将会带来全新的体验哦: Markdown和扩展Markdown简洁的语法 代码块高亮 图片链接和...
  • qq_27437671
  • qq_27437671
  • 2017年11月10日 15:51
  • 54

[libxml2]_[C/C++]_[使用libxml2读取内存的xml片段]

场景: 1.有时候需要读取其他的xml片段输出组合成一个完整的xml文档. 2.或者对内存xml进行修改. void ReadXmlFromMemory() { string source =...
  • infoworld
  • infoworld
  • 2013年09月13日 17:31
  • 2068

Libxml2如何生成格式化的XML文件

一、问题 默认的Libxml2在写入XML文件时,都是将所有内容写成一行的,不便于文本查看。其实Libxml2是可以生成格式化的XML文件的。 二、解决方法 1)打开开关 xmlKee...
  • slowwind2007_lishu
  • slowwind2007_lishu
  • 2014年03月21日 13:25
  • 1947
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:libxml的使用(1)--读取xml
举报原因:
原因补充:

(最多只允许输入30个字)