libxml2剖析(1):功能特性

来源:互联网 发布:1942芬兰怪物知乎 编辑:程序博客网 时间:2024/06/05 00:17
1、概述
    本文整理自官方页面http://xmlsoft.org/。
    Libxml2是一个用来解析XML文档的函数库。它用C语言写成,并且能为多种语言所调用,例如C语言, C++, C#, Python, Kylix/Delphi, PHP, Ruby, Pascal, Tcl等。Perl中也可以使用XML::LibXML模块。它最初是为GNOME开发的项目,但现在可以用在各种各样的场合。libXML2代码可移植性非常好,因为它基于标准的ANSI C,并采用MIT许可证。它可以移植到各种各样的系统,包括Linux, Unix, Windows, CygWin, MacOS, MacOS X, RISC Os, OS/2, VMS, QNX, MVS, VxWorks等等。
    可从ftp://xmlsoft.org/libxml2/处下载libxml2的最新源码,当前为libxml2-2.9.0.tar.gz,解开后可以看到,源文件都在根目录下,所有文档在doc目录,头文件在include/libxml/目录下。
    Libxml2实现了一系列与标记语言相关的标准:
    (1)XML标准:http://www.w3.org/TR/REC-xml
    (2)XML命名空间:http://www.w3.org/TR/REC-xml-names/
    (3)XML Base: http://www.w3.org/TR/xmlbase/
    (4)RFC 2396: 统一资源标识符(URI),http://www.ietf.org/rfc/rfc2396.txt
    (5)XML路径语言(XPath) 1.0: http://www.w3.org/TR/xpath
    (6)HTML4解析器: http://www.w3.org/TR/html401/
    (7)XML指针语言(XPointer)版本1.0: http://www.w3.org/TR/xptr
    (8)XML包含机制(XInclude)版本1.0: http://www.w3.org/TR/xinclude/
    (9)ISO-8859-x编码,还有rfc2044[UTF-8]和rfc2781[UTF-16]的Unicode编码,通过使用iconv库,还可以支持更多其他的编码(如亚洲语言的编码)
    (10)SGML开放技术方案TR9401:1997的部分特性
    (11)XML目录(XML Catalogs)工作草案: http://www.oasis-open.org/committees/entity/spec-2001-08-06.html
    (12)规范化XML(Canonical XML)版本1.0: http://www.w3.org/TR/xml-c14n,以及规范化算法(Exclusive XML Canonicalization CR草案) http://www.w3.org/TR/xml-exc-c14n
    (13)Relax NG, ISO/IEC 19757-2:2003, http://www.oasis-open.org/committees/relax-ng/spec-20011203.html
    (14)W3C XML Schemas第二部分: 数据类型 http://www.w3.org/TR/2001/REC-xmlschema-2-20010502/
    (15)W3C xml:id工作草案(2004-04-07): http://www.w3.org/TR/xml-id/
    大部分情况下libxml2以严格兼容的方式实现这些规范。从2.4.16版开始,libxml2通过了来自OASIS XML Tests Suite(http://www.oasis-open.org/committees/xml-conformance/)的所有1800多个测试。
    libxml2提供了对下列规范提供了一定程度的支持,但还没有对这些规范提供完整全面地支持:
    (1)文档对象模型(DOM) http://www.w3.org/TR/DOM-Level-2-Core/:文档模型,但没有实现API自身,gdome2在libxml2之上完成这项工作。
    (2)RFC 959: libxml2实现了基本的FTP客户代码。
    (3)RFC 1945: HTTP/1.0,以及基本的HTTP客户代码。
    (4)SAX: 一个SAX2风格的接口,和一个兼容早期expat版本的最小限度的SAX1实现。
    XML Schemas第一部分:结构(http://www.w3.org/TR/2001/REC-xmlschema-1-20010502/)的部分实现正在进行。
    下面是一些独立的文档:
    (1)libxslt: http://xmlsoft.org/XSLT/,为libxml2提供一个XSLT 1.0的实现,和类似于EXSLT的常用扩展。
    (2)gdome2: http://gdome2.cs.unibo.it/,为libxml2提供一个标准的DOM2实现。
    (3)XMLSec: http://www.aleksey.com/xmlsec/,为libxml2提供W3C XML数字签名(http://www.w3.org/TR/xmldsig-core/)的实现。
    Libxml2的一些关键特性可归纳如下:
    (1)对XML和HTML,都提供推模式(前进式的)或拉模式(阻塞式的)的解析接口。
    (2)使用一个要解析的文档实例或附带一个任意的DTD,可以在解析时做DTD验证。
    (3)包含完整的XPath, XPointer和XInclude实现。
    (4)用纯C编写,尽可能少的依赖,遵循ANSI C/POSIX标准以便容易嵌入到其他程序中。可以工作在Linux/Unix/Windows上,还移植到其他的很多平台。
    (5)基本的HTTP和FTP客户端支持,从而允许应用程序获取远程资源。
    (6)设计是模块化的,许多扩展可以独立编译。
    (7)内部文档表示尽可能靠近DOM接口规范。
    (8)也提供SAX风格的接口,它被设计成与Expat兼容(http://sourceforge.net/projects/expat,另外一个XML解析库)。
    (9)本库在MIT许可证下发布。
    2、数据类型
    Libxml2定义了一些经常要用到的数据类型,以隐藏一些繁杂的底层处理。
    (1)字符类型xmlChar
    这是Libxml2中的字符类型,库中所有字符、字符串都是基于这个数据类型。事实上它的定义在xmlstring.h中。
typedef unsigned char xmlChar;
    它表示UTF-8编码的字符串的一个字节。如果你的数据使用其他的编码,则需要使用libxml中的函数转换成UTF-8编码。如同标准C中的char类型一样,xmlChar也有相关的动态内存分配、字符串操作等函数。例如xmlMalloc是动态分配内存的函数;xmlFree是配套的释放内存函数;xmlStrcmp是字符串比较函数等等。基本上xmlChar字符串相关函数都在xmlstring.h中定义;而动态内存分配函数在xmlmemory.h中定义。
    外要注意,因为总是要在xmlChar*和char*之间进行类型转换,所以定义了一个宏BAD_CAST,其定义如下(xmlstring.h):
#define BAD_CAST (xmlChar *)
    原则上来说,unsigned char和char之间进行强制类型转换是没有问题的。
    (2)文档类型xmlDoc、指针xmlDocPtr
    定义在tree.h中。xmlDoc是一个struct,保存了一个xml文档的相关信息,例如文件名、文档类型、节点树等等;xmlDocPtr等于xmlDoc*,它搞成这个样子总让人以为是智能指针,其实不是,要手动删除的。
    xmlNewDoc函数创建一个新的文档指针。xmlParseFile函数以默认方式读入一个UTF-8格式的文档,并返回文档指针。xmlReadFile函数读入一个带有某种编码的xml文档,并返回文档指针;细节见libxml2参考手册。
    xmlFreeDoc释放文档指针。特别注意,当你调用xmlFreeDoc时,该文档所有包含的节点内存都被释放,所以一般来说不需要手动调用xmlFreeNode或者xmlFreeNodeList来释放动态分配的节点内存,除非你把该节点从文档中移除了。一般来说,一个文档中所有节点都应该动态分配,然后加入文档,最后调用xmlFreeDoc一次释放所有节点申请的动态内存,这也是为什么我们很少看见xmlNodeFree的原因。
    xmlSaveFile将文档以默认方式存入一个文件。xmlSaveFormatFileEnc可将文档以某种编码/格式存入一个文件中。
    (3)节点类型xmlNode、指针xmlNodePtr

    定义在tree.h中。节点应该是xml中最重要的元素了,xmlNode代表了xml文档中的一个节点,实现为一个struct,内容很丰富。

[cpp] view plaincopy
  1. /** 
  2.  * xmlNode: 
  3.  * 
  4.  * A node in an XML tree. 
  5.  */  
  6. typedef struct _xmlNode xmlNode;  
  7. typedef xmlNode *xmlNodePtr;  
  8. struct _xmlNode {  
  9.     void           *_private;   /* application data */  
  10.     xmlElementType   type;  /* type number, must be second ! */  
  11.     const xmlChar   *name;      /* the name of the node, or the entity */  
  12.     struct _xmlNode *children;  /* parent->childs link */  
  13.     struct _xmlNode *last;  /* last child link */  
  14.     struct _xmlNode *parent;    /* child->parent link */  
  15.     struct _xmlNode *next;  /* next sibling link  */  
  16.     struct _xmlNode *prev;  /* previous sibling link  */  
  17.     struct _xmlDoc  *doc;   /* the containing document */  
  18.   
  19.     /* End of common part */  
  20.     xmlNs           *ns;        /* pointer to the associated namespace */  
  21.     xmlChar         *content;   /* the content */  
  22.     struct _xmlAttr *properties;/* properties list */  
  23.     xmlNs           *nsDef;     /* namespace definitions on this node */  
  24.     void            *psvi;  /* for type/PSVI informations */  
  25.     unsigned short   line;  /* line number */  
  26.     unsigned short   extra; /* extra data for XPath/XSLT */  
  27. };  
    可以看到,节点之间是以链表和树两种方式同时组织起来的,next和prev指针可以组成链表,而parent和children可以组织为树。同时还有以下重要元素:节点中的文字内容content;节点所属文档doc;节点名字name;节点的名称空间ns;节点属性列表properties等。
    Xml文档的操作的根本原理就是在节点之间移动、查询节点的各项信息,并进行增加、删除、修改的操作。xmlNodePtr指针用来遍历文档树。
    xmlDocSetRootElement函数可以将一个节点设置为某个文档的根节点,这是将文档与节点连接起来的重要手段,当有了根结点以后,所有子节点就可以依次连接上根节点,从而组织成为一个xml树。
    (3)节点集合类型xmlNodeSet、指针xmlNodeSetPtr
    节点集合代表一个由节点集组成的变量,节点集合只作为Xpath的查询结果而出现,因此被定义在xpath.h中,其定义如下:
[cpp] view plaincopy
  1. /* 
  2.  * A node-set (an unordered collection of nodes without duplicates). 
  3.  */  
  4. typedef struct _xmlNodeSet xmlNodeSet;  
  5. typedef xmlNodeSet *xmlNodeSetPtr;  
  6. struct _xmlNodeSet {  
  7.     int nodeNr;         /* number of nodes in the set */  
  8.     int nodeMax;        /* size of the array as allocated */  
  9.     xmlNodePtr *nodeTab;    /* array of nodes in no particular order */  
  10.     /* @@ with_ns to check wether namespace nodes should be looked at @@ */  
  11. };  

    可以看出,节点集合有三个成员,分别是节点集合的节点数、最大可容纳的节点数,以及节点数组头指针。对节点集合中各个节点的访问方式很简单,如下:

[cpp] view plaincopy
  1. xmlNodeSetPtr nodeset = XPATH查询结果;  
  2. for (int i = 0; i < nodeset->nodeNr; i++)  
  3. {  
  4.     nodeset->nodeTab[i];  
  5. }  

     注意,libxml2是一个C函数库,因此其函数和数据类型都使用C语言的方式来处理。如果是C++,用STL中的vector来表示一个节点集合会更好,而且没有内存泄漏或者溢出的担忧。

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 个税申报错税局查出来怎么办 苹果手表抬腕唤醒失灵怎么办 在京东充电费充错了怎么办 进去了微商传销怎么办 喝完酒四肢酸痛睡不着怎么办 喝多了全身痛怎么办 喝完酒第二天浑身酸痛怎么办 鑫和陌车骗我钱怎么办 社会人加你qq怎么办 有人问你加qq怎么办 住酒店遇到被色情诈骗怎么办 怎么办我陷入感情骗局了 移动手机卡被强制停机怎么办 诚e赊套现被骗了怎么办 钻戒小了怎么办小窍门 爱用商城逾期了怎么办 工程骗局洗脑了怎么办 还网贷客服电话打不通怎么办 中信客服电话打不通怎么办 亚马逊客服电话打不通怎么办 安卓软件闪退怎么办? 吃鸡麦克风炸麦怎么办 美版iphone屏摔了怎么办 天地荣域四十后怎么办 淘宝拍下商品不付款怎么办 淘宝买东西取消订单淘金币怎么办 淘宝淘金币快过期了怎么办 公众号密码忘了怎么办 酷狗直播个入驻粉丝少怎么办 健康证预约显示未接收怎么办 在互惠车贷逾期怎么办 天天中彩票怎么登陆不了怎么办 正宇新商城不能提现怎么办 融e购买完不发货怎么办 婴儿肚子胀气肚脐凸出来怎么办 微信商城买东西被骗了怎么办 拼多多商家不发货怎么办 鞋上的饰品掉了怎么办 饰品上的钻掉了怎么办 dota2饰品被好友礼物怎么办 dota2接收的礼物打不开怎么办