当前位置: 首页 > 工具软件 > LibXML2 > 使用案例 >

简谈libxml2库函数的使用

史意致
2023-12-01


前言

在做4G拨号的时候,遇到从.xml文件获取数据的部分。所以趁机简单在菜鸟教程学习了xml。在使用libxml2库的时候,我们有必要先了解一下xml的语法规则。在了解xml的时候顺带又把HTML过了一下。


提示:以下是本篇文章正文内容,下面案例可供参考

一、XML简介

1.1 什么是XML

  1. XML 指可扩展标记语言(EXtensible Markup Language)。
  2. XML 是一种很像HTML的标记语言。
  3. XML的设计宗旨是传输数据,而不是显示数据。
  4. XML 标签没有被预定义。您需要自行定义标签。
  5. XML 被设计为具有自我描述性。
  6. XML 是W3C 的推荐标准。

1.2 XML 和 HTML 之间的差异

1、XML 不是 HTML 的替代。
2、XML 和 HTML 为不同的目的而设计:

  1. XML被设计用来传输和存储数据,其焦点是数据的内容。
  2. HTML 被设计用来显示数据,其焦点是数据的外观。

3、HTML 旨在显示信息,而 XML 旨在传输信息。
4、XML 是对 HTML 的补充。

1.3 浅谈个人对XML的理解

在不谈语法规则的情况下,我们可以把XML看成是一棵树。是一颗每个节点都可以有属性的树,我们再通过API函数接口对其读取数据是也是通过类似对数的遍历来对其进行增删改查的。我是通过使用libxml2库来对.xml文件进行解析的,下面来给大家简单的介绍一下libxml2库的使用。

二、libxml2简介

(具体的介绍就参考 http://xmlsoft.org/ 推荐英文好的去看)
Libxml2 是一个xml c语言版的解析器,本来是为Gnome项目开发的工具,是一个基于MIT License的免费开源软件。它除了支持c语言版以外,还支持c++、PHP、Pascal、Ruby、Tcl等语言的绑定,能在Windows、Linux、Solaris、MacOsX等平台上运行。功能还是相当强大的,相信满足一般用户需求没有任何问题。

Libxml2主要的优点有:

  1. 安装、使用比较简单,容易入门;
  2. 支持的编码格式较多,能很好的解决中文问题(使用一个很简单的编码转换函数);
  3. 支持Xpath解析(这点对于任意定位xml文档中的节点还是很有用的哦);
  4. 支持Well-formed 和valid验证,具体而言支持DTD验证,Schema验证功能正在完善中(目前多数解析器都还不完全支持shema验证功能);
  5. 支持目前通用的Dom、Sax方式解析等等。

不足之处也是有的:

  1. 指针太多,使用不当时就会出现错误,在Linux系统中表现为常见的段错误,同样管理不当易造成内存泄漏;
  2. 个人认为内面有些函数的功能设计的不是很好(比如获取Xpath函数,它不获取节点属性,这样子有些情况会定位不准)

三、libxml2库的安装

1、 下载libxml2
可从http://xmlsoft.org/官网下载,或者githome上自行下载。
2、 具体安装步骤
原码安装:

  1. 解压:$tar zxvf libxml2-2.6.20.tar.gz

  2. 进入解压后的安装目录:$cd libxml2-2.6.20

  3. 安装三部曲:

  $./configure
  $make
  $make install

(在这里不推荐使用shell命令直接安装)
shell命令安装:

$ sudo apt-get install libxml2 
$ sudo apt-get install libxml2-dev

四、libxml2中主要数据结构和常用函数

他的函数主要都在一下三个头文件:
#include <libxml/parse.h>
#include <libxml/tree.h>
#include <libxml/xpath.h>

4.1 主要数据结构

1.1 xml操作的基础结构及其指针类型
xmlDoc xmlDocPtr 文档对象的结构体及其指针
xmlNode xmlNodePtr 节点对象的结构体及其指针
xmlAttr xmlAttrPtr 节点属性的结构体及其指针
xmlNs xmlNsPtr 节点命名空间的结构及其指针

在上述的所以节点当中我们必须把xmlNode节点类型给搞明白了,这个节点可以说是这个库中最重要的一个节点。具体结构如下说明:

typedef struct _xmlNode xmlNode;

typedef xmlNode *xmlNodePtr;

struct _xmlNode {
    void           *_private;/* application data */
    xmlElementType   type;   /* type number, must be second ! */
    const xmlChar   *name;      /* the name of the node, or the entity */
    struct _xmlNode *children; /* parent->childs link */
    struct _xmlNode *last;   /* last child link */
    struct _xmlNode *parent;/* child->parent link */
    struct _xmlNode *next;   /* next sibling link */
    struct _xmlNode *prev;   /* previous sibling link */
    struct _xmlDoc *doc;/* the containing document */
    /* End of common part */
    xmlNs           *ns;        /* pointer to the associated namespace */
    xmlChar         *content;   /* the content */
    struct _xmlAttr *properties;/* properties list */
    xmlNs           *nsDef;     /* namespace definitions on this node */
    void            *psvi;/* for type/PSVI informations*/
    unsigned short   line;   /* line number */
    unsigned short   extra; /* extra data for XPath/XSLT */
};

XML属性也是编程中经常用到的结构,其定义如下:

struct _xmlAttr {
    void *    _private;   /* application data */
    xmlElementType type;  /* XML_ATTRIBUTE_NODE, must be second !  */
    const xmlChar *    name ;  /*the name of the property */
    struct _xmlNode *  children;  /*the value of the property */
    struct _xmlNode *  last;  /*NULL */
    struct _xmlNode *  parent;  /*child->parent link */
    struct _xmlAttr *  next;  /*next sibling link */
    struct _xmlAttr *  prev;  /*previous sibling link */
    struct _xmlDoc *   doc;  /*the containing document */
    xmlNs *   ns;  /*pointer to the associated namespace */
    xmlAttributeType   atype;  /*the attribute type if validating */
    void *    psvi;  /*for type/PSVI informations */

};

1.2 内部字符类型xmlChar

xmlChar是Libxml2中的字符类型,库中所有字符、字符串都是基于这个数据类型。事实上他的定义是:xmlstring.h

如同标准c中的char类型相同,xmlChar也有动态内存分配、字符串操作等相关函数。例如xmlMalloc是动态分配内存的函数;xmlFree是配套的释放内存函数;xmlStrcmp是字符串比较函数等等。

另外要注意,因为总是要在xmlChar和char之间进行类型转换,所以定义了一个宏BAD_CAST,其定义如下:xmlstring.h

#define BAD_CAST (xmlChar *)

4.2 常用函数

1、清除空白符影响函数

函数功能在分析XML数据是,去除空白字符。如果不去除空白字符,则这些字符也会被当做一个node来处理
函数接口int xmlKeepBlanksDefault(int val)
参数说明val:0或者1。0表示去除空白字符,1表示不去除返回值:0表示设置失败,1表示设置成功,一般不用判断
特别说明在每一次迭代时最好都是使用,在我亲测的过程中发现每遇到一个空白行他就得调用一次,否则取出来的节点名是text(libxml2的所有库函数都会把空白符当作一个node)

2、打开XML文档

函数功能读出XML文档指针doc
函数接口xmlDocPtr xmlReadFile (const char * filename, const char * encoding, int options)
参数说明filename: 目标文件的路径名或URL; encoding: 目标文件的编码方式,可以为NULL ; options: 枚举变量xmlParserOption中的一个值或多个值的组合,可以为0; 返回值: XML文档的树结构。解析失败返回NULL
特别说明

3、 XML文件载入和保存函数

函数功能将XML文件从硬盘上载入到内存中,并且生成DOM树。使用完毕之后,需要用xmlFreeDoc()来释放资源
函数接口xmlDocPtr xmlParseFile(const char * filename)
参数说明filename:XML文件名称。返回值:如果载入成功,则返回这个文档的根节点。否则返回NULL
特别说明该函数没有亲测过,但知道其是怎么使用的。就类似与word里的保存,在添加完所有的节点,节点属性后再关闭该文当前调用其进行保存

4、创建和释放XML文档函数

函数功能在内存中创建一个新的XML文档。所创建的文档需要使用xmlFreeDoc()来释放资源
函数接口xmlDocPtr xmlNewDoc (const xmlChar * version)
参数说明version:XML标准的版本,目前只能指定为“1.0”
特别说明使用时记得强制转换一下类型;
函数功能释放内存中的XML文档
函数接口void xmlFreeDoc(xmlDocPtr cur)
参数说明cur:需要释放的XML文档
特别说明在打开文档后也要释放文档;

5、XML节点操作函数

函数功能获得根节点
函数接口xmlNodePtr xmlDocGetRootElement(xmlDocPtr doc)
参数说明doc:XML文档句柄。返回值:XML文档的根节点,或者NULL。
特别说明
函数功能设置根节点
函数接口xmlNodePtr xmlDocSetRootElement(xmlDocPtr doc, xmlNodePtr root)
参数说明doc:XML文档句柄root:XML文档的新的根节点返回值:如果该文档原来有根节点,则返回根节点,否则返回NULL
特别说明
函数功能查找节点
函数接口void xmlStrcmp(xmlNodePtr *cur, xmlChar * Nodename)
参数说明cur:节点的指针;Nodename:所要查找的节点名字;返回值:0;如果没有该节点,则返回-1。
特别说明
函数功能获得节点的内容
函数接口xmlChar * xmlNodeGetContent (xmlNodePtr cur)
参数说明cur:节点的指针;返回值:节点的文本内容。如果该节点没有文本内容,则返回NULL。当返回值不为NULL时,需要用xmlFree()函数来释放返回的资源
特别说明
函数功能设置节点的内容长度
函数接口void xmlNodeSetContentLen(xmlNodePtr cur, const xmlChar * content, int len)
参数说明cur:节点的指针 ; content:节点的新文本内容; len:节点新文本内容的长度
特别说明
函数功能判断该节点是否具有属性
函数接口xmlNodePtr xmlHasProp( xmlNodePtr cur, xmlChar *propNode)
参数说明cur:节点的指针 ; propNode:属性名 ; 返回值:成功为节点指针
特别说明
函数功能获得节点的属性
函数接口xmlChar * xmlGetProp(xmlNodePtr node, const xmlChar * name)
参数说明node:XML节点的指针; name:该节点的属性的名称; 返回值:该属性的值或者为NULL。如果不为NULL,则需要用xmlFree()来释放资源
特别说明
函数功能设置节点的属性(如果该属性已经存在,则替换其值)
函数接口xmlAttrPtr xmlSetProp(xmlNodePtr node, const xmlChar * name, const xmlChar * value)
参数说明node:需要设置属性的节点; name:该节点的属性的名称;value:属性的值; 返回值:该属性的值
特别说明

libxml2库还有大量的API接口,这里就不列举了(本人也没有全部搞明白,需要的可以到使用手册里查找,或者官网查询)。


总结

在小编学习使用libxml2库的时候,也绕了很多坑。现在吧我所用到的都写到博客里记录下来在以后使用到时候能立即那里使用,在查找根节点的root->xmlChildrenNode->xmlChildrenNode 的属性的时候真的是被这个指针搞得头晕,出现了死循环。在调试的时候必须画图理解一下。还有就是text节点,每一个空白行都被当作一个node,每一次迭代前最好都加 xmlKeepBlanksDefault(0); 忽略空白符。

参考资料:
https://blog.csdn.net/fanwenjieok/article/details/52847105
https://www.runoob.com/xml/xml-usage.html

 类似资料: