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

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。

接下来就是解析文件了。

[cpp] view plaincopyprint?

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

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

[cpp] view plaincopyprint?

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

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

[cpp] view plaincopyprint?

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

[cpp] view plaincopyprint?

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

[cpp] view plaincopyprint?

  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. }

这是完整的源码。

[cpp] view plaincopyprint?

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

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

[cpp] view plaincopyprint?

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

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

修改后结果如下:

[cpp] view plaincopyprint?

  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也能实现这样的功能。

[cpp] view plaincopyprint?

  1. static char* config = "<config />";
  2. xmlDocPtr doc = NULL;
  3. xmlKeepBlanksDefault(0);
  4. doc = xmlReadMemory(config, strlen(config), "in_memory.xml", NULL, 0);
  5. //handle doc
  6. xmlFreeDoc(doc);
0
时间: 2025-01-02 00:24:04

libxml的使用(1)--读取xml的相关文章

windows 系统在vs2010 中配置libxml2,及读取xml代码例子

1.先下载libxml2 (下载地址 http://download.csdn.net/detail/luoww1/8095273),里面包括了三个文件夹分别:zlib-1.2.3.win32 和iconv-1.9.2.win32 和libxml2-2.7.6.win32 2.将下载内容中的iconv.dll 和zlib1.dll 拷贝到C盘下的Windows文件夹中 3.在项目中新建include 文件夹,解压的到的libxml2和iconv中的include文件夹中的内容拷入到该includ

android XMLPullParser读取xml文件

由于刚学Android,用的开发工具是Android studio,没用过eclipse的那个开发Android,所以针对有些说由于2个IDE的路径不通导致的文件读取不到,不做分析(实际上是没法分析eclipse里的),这个博文只针对AS用户. 我们的资源文件,除了放到res目录下之外,还可以放在跟java .res同级的asserts(新建的)目录里. 今天要解析的这个xml就是在这个目录下的. 首先说一下xmlpullparser,这个pull解析是基于事件的模式.比如 读取到xml的开始声

C#读取XML文件的基类实现

刚到新单位,学习他们的源代码,代码里读写系统配置文件的XML代码比较老套,直接写在一个系统配置类里,没有进行类的拆分,造成类很庞大,同时,操作XML的读写操作都是使用SetAttribute和node.Attribute(name)方法,因此,想到结合之前所做的XML操作,完成了一个能够读取XML文件的基类,便于以后的使用. PS:即使再老套的代码,目前也不敢进行优化,一是水平不行,二是不敢. 使用静态扩展类,扩展了几个经常使用的类型,能够方便数据的读写. 操作XML的类,可以直接继承BaseL

【XML配置文件读取】使用jdom读取XML配置文件信息

在项目中我们经常需要将配置信息写在配置文件中,而XML配置文件是常用的格式. 下面将介绍如何通过jdom来读取xml配置文件信息. 配置文件信息 <?xml version="1.0" encoding="UTF-8"?> <config> <base-config> <stringValue>Hello world</stringValue> <integerValue>8</integ

C#中使用XML指南之读取XML

? C#中使用XML指南之读取XML ? 访问的两种模型: ? 在程序中访问进而操作XML文件一般有两种模型,分别是使用DOM(文档对象模型)和流模型,使用DOM的好处在于它允许编辑和更新XML文档,可以随机访问文档中的数据,可以使用XPath查询,但是,DOM的缺点在于它需要一次性的加载整个文档到内存中,对于大型的文档,这会造成资源问题.流模型很好的解决了这个问题,因为它对XML文件的访问采用的是流的概念,也就是说,任何时候在内存中只有当前节点,但它也有它的不足,它是只读的,仅向前的,不能在文

用C#读取XML文档

本文将以一个非常简单的例子来说明如何使用C#访问一个XML文件并且读取其中的信息.例子本身并无任何实际意义,它只是简单的介绍了如何调用微软的XML标准以及如何运用到实际当中去.希望能够对初次接触C#或者未尝试过通过C#读取XML文件的读者有所启发.本文旨在抛砖引玉,希望能与更多的朋友交流和分享经验.    制作过程 1. 运行Visual Studio.NET,新建Visual C#.NET工程,这里取名为ReadXML. 2. 在解决方案资源管理器中,将Form1.cs改名为frmAuthor

读取xml并将节点保存到Excal

using NPOI.HPSF; using NPOI.HSSF.UserModel; using NPOI.SS.UserModel; using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.IO; using System.Linq; using System.Text; using Sy

Excel开发学习笔记:读取xml文件及csv文件

读取xml文件 有好多种读取xml的方式,xmlDOM比较常见,我使用了另外一种,它以数据流的方式打开文件并读取内容 Imports System.Xml  Dim group As New List(Of String)  Using reader As XmlReader = XmlReader.Create(OpenFileDialog2.FileName)      While reader.ReadToFollowing("group")          reader.Mo

C# 递归读取XML菜单数据

在博客园注册了有4年了,很遗憾至今仍未发表过博客,趁周末有空发表第一篇博客.小生不才,在此献丑了! 最近在研究一些关于C#的一些技术,纵观之前的开发项目的经验,做系统时显示系统菜单的功能总是喜欢把数据写在数据库表,然后直接读取加载到菜单树上显示. 现在想把菜单数据都放在XML里,然后递归读取XML. 由于项目使用WCF,实体类使用了两个,一个是业务逻辑层中的实体,一个是调用业务逻辑层递归方法后进行数据实体的转换,XML读取方法写在业务逻辑层中. 思路:1.先读取XML里所有的菜单    2.根据