C的xml编程libxml2.docx

上传人:b****6 文档编号:13332042 上传时间:2023-06-13 格式:DOCX 页数:23 大小:25.92KB
下载 相关 举报
C的xml编程libxml2.docx_第1页
第1页 / 共23页
C的xml编程libxml2.docx_第2页
第2页 / 共23页
C的xml编程libxml2.docx_第3页
第3页 / 共23页
C的xml编程libxml2.docx_第4页
第4页 / 共23页
C的xml编程libxml2.docx_第5页
第5页 / 共23页
C的xml编程libxml2.docx_第6页
第6页 / 共23页
C的xml编程libxml2.docx_第7页
第7页 / 共23页
C的xml编程libxml2.docx_第8页
第8页 / 共23页
C的xml编程libxml2.docx_第9页
第9页 / 共23页
C的xml编程libxml2.docx_第10页
第10页 / 共23页
C的xml编程libxml2.docx_第11页
第11页 / 共23页
C的xml编程libxml2.docx_第12页
第12页 / 共23页
C的xml编程libxml2.docx_第13页
第13页 / 共23页
C的xml编程libxml2.docx_第14页
第14页 / 共23页
C的xml编程libxml2.docx_第15页
第15页 / 共23页
C的xml编程libxml2.docx_第16页
第16页 / 共23页
C的xml编程libxml2.docx_第17页
第17页 / 共23页
C的xml编程libxml2.docx_第18页
第18页 / 共23页
C的xml编程libxml2.docx_第19页
第19页 / 共23页
C的xml编程libxml2.docx_第20页
第20页 / 共23页
亲,该文档总共23页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

C的xml编程libxml2.docx

《C的xml编程libxml2.docx》由会员分享,可在线阅读,更多相关《C的xml编程libxml2.docx(23页珍藏版)》请在冰点文库上搜索。

C的xml编程libxml2.docx

C的xml编程libxml2

C的xml编程-libxml2

C的xml编程-libxml2这里主要讲述libxml2在linux下的使用。

(以下内容除了linux下的安装步骤是自己写的,其余均出自

1.下载与安装LIBXML2

Libxml2是一个C语言的XML程序库,可以简单方便的提供对XML文档的各种操作,并且支持XPATH查询,以及部分的支持XSLT转换等功能。

Libxml2的下载地址是http:

//xmlsoft.org/,完全版的库是开源的,并且带有例子程序和说明文档。

最好将这个库先下载下来,因为这样可以查看其中的文档和例子。

由于我是在linux下用C语言进行开发的,所以我下载的是libxml2-2.6.20.tar.gz版本的源码包。

具体安装步骤:

1、解压:

$tarzxvflibxml2-2.6.20.tar.gz

2、进入解压后的安装目录:

$cdlibxml2-2.6.20

3、安装三部曲:

1)$./configure

2)$make

3)$makeinstall

安装完毕。

2.Libxml2中的数据类型和函数

一个函数库中可能有几百种数据类型以及几千个函数,但是记住大师的话,90%的功能都是由30%的内容提供的。

对于libxml2,我认为搞懂以下的数据类型和函数就足够了。

2.1内部字符类型xmlChar

xmlChar是Libxml2中的字符类型,库中所有字符、字符串都是基于这个数据类型。

事实上它的定义是:

xmlstring.h

typedefunsignedcharxmlChar;

使用unsignedchar作为内部字符格式是考虑到它能很好适应UTF-8编码,而UTF-8编码正是libxml2的内部编码,其它格式的编码要转换为这个编码才能在libxml2中使用。

还经常可以看到使用xmlChar*作为字符串类型,很多函数会返回一个动态分配内存的xmlChar*变量,使用这样的函数时记得要手动删除内存。

2.2xmlChar相关函数

如同标准c中的char类型一样,xmlChar也有动态内存分配、字符串操作等相关函数。

例如xmlMalloc是动态分配内存的函数;xmlFree是配套的释放内存函数;xmlStrcmp是字符串比较函数等等。

基本上xmlChar字符串相关函数都在xmlstring.h中定义;而动态内存分配函数在xmlmemory.h中定义。

2.3xmlChar*与其它类型之间的转换

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

xmlstring.h

#defineBAD_CAST(xmlChar*)

原则上来说,unsignedchar和char之间进行强制类型转换是没有问题的。

2.4文档类型xmlDoc、指针xmlDocPtr

xmlDoc是一个struct,保存了一个xml的相关信息,例如文件名、文档类型、子节点等等;xmlDocPtr等于xmlDoc*,它搞成这个样子总让人以为是智能指针,其实不是,要手动删除的。

xmlNewDoc函数创建一个新的文档指针。

xmlParseFile函数以默认方式读入一个UTF-8格式的文档,并返回文档指针。

xmlReadFile函数读入一个带有某种编码的xml文档,并返回文档指针;细节见libxml2参考手册。

xmlFreeDoc释放文档指针。

特别注意,当你调用xmlFreeDoc时,该文档所有包含的节点内存都被释放,所以一般来说不需要手动调用xmlFreeNode或者xmlFreeNodeList来释放动态分配的节点内存,除非你把该节点从文档中移除了。

一般来说,一个文档中所有节点都应该动态分配,然后加入文档,最后调用xmlFreeDoc一次释放所有节点申请的动态内存,这也是为什么我们很少看见xmlNodeFree的原因。

xmlSaveFile将文档以默认方式存入一个文件。

xmlSaveFormatFileEnc可将文档以某种编码/格式存入一个文件中。

2.5节点类型xmlNode、指针xmlNodePtr

节点应该是xml中最重要的元素了,xmlNode代表了xml文档中的一个节点,实现为一个struct,内容很丰富:

tree.h

typedefstruct_xmlNodexmlNode;

typedefxmlNode*xmlNodePtr;

struct_xmlNode{

void*_private;/*applicationdata*/

xmlElementTypetype;/*typenumber,mustbesecond!

*/

constxmlChar*name;/*thenameofthenode,ortheentity*/

struct_xmlNode*children;/*parent->childslink*/

struct_xmlNode*last;/*lastchildlink*/

struct_xmlNode*parent;/*child->parentlink*/

struct_xmlNode*next;/*nextsiblinglink*/

struct_xmlNode*prev;/*previoussiblinglink*/

struct_xmlDoc*doc;/*thecontainingdocument*/

/*Endofcommonpart*/

xmlNs*ns;/*pointertotheassociatednamespace*/

xmlChar*content;/*thecontent*/

struct_xmlAttr*properties;/*propertieslist*/

xmlNs*nsDef;/*namespacedefinitionsonthisnode*/

void*psvi;/*fortype/PSVIinformations*/

unsignedshortline;/*linenumber*/

unsignedshortextra;/*extradataforXPath/XSLT*/

};

可以看到,节点之间是以链表和树两种方式同时组织起来的,next和prev指针可以组成链表,而parent和children可以组织为树。

同时还有以下重要元素:

l节点中的文字内容:

content;

l节点所属文档:

doc;

l节点名字:

name;

l节点的namespace:

ns;

l节点属性列表:

properties;

Xml文档的操作其根本原理就是在节点之间移动、查询节点的各项信息,并进行增加、删除、修改的操作。

xmlDocSetRootElement函数可以将一个节点设置为某个文档的根节点,这是将文档与节点连接起来的重要手段,当有了根结点以后,所有子节点就可以依次连接上根节点,从而组织成为一个xml树。

2.6节点集合类型xmlNodeSet、指针xmlNodeSetPtr

节点集合代表一个由节点组成的变量,节点集合只作为Xpath的查询结果而出现(XPATH的介绍见后面),因此被定义在xpath.h中,其定义如下:

/*

*Anode-set(anunorderedcollectionofnodeswithoutduplicates).

*/

typedefstruct_xmlNodeSetxmlNodeSet;

typedefxmlNodeSet*xmlNodeSetPtr;

struct_xmlNodeSet{

intnodeNr;/*numberofnodesintheset*/

intnodeMax;/*sizeofthearrayasallocated*/

xmlNodePtr*nodeTab;/*arrayofnodesinnoparticularorder*/

/*@@with_nstocheckwethernamespacenodesshouldbelookedat@@*/

};

可以看出,节点集合有三个成员,分别是节点集合的节点数、最大可容纳的节点数,以及节点数组头指针。

对节点集合中各个节点的访问方式很简单,如下:

xmlNodeSetPtrnodeset=XPATH查询结果;

for(inti=0;i<nodeset->nodeNr;i++)

{

nodeset->nodeTab[i];

}

注意,libxml2是一个c函数库,因此其函数和数据类型都使用c语言的方式来处理。

如果是c++,我想我宁愿用STL中的vector来表示一个节点集合更好,而且没有内存泄漏或者溢出的担忧。

3.简单xml操作例子

了解以上基本知识之后,就可以进行一些简单的xml操作了。

当然,还没有涉及到内码转换(使得xml中可以处理中文)、xpath等较复杂的操作。

3.1创建xml文档

有了上面的基础,创建一个xml文档显得非常简单,其流程如下:

l用xmlNewDoc函数创建一个文档指针doc;

l用xmlNewNode函数创建一个节点指针root_node;

l用xmlDocSetRootElement将root_node设置为doc的根结点;

l给root_node添加一系列的子节点,并设置子节点的内容和属性;

l用xmlSaveFile将xml文档存入文件;

l用xmlFreeDoc函数关闭文档指针,并清除本文档中所有节点动态申请的内存。

注意,有多种方式可以添加子节点:

第一是用xmlNewTextChild直接添加一个文本子节点;第二是先创建新节点,然后用xmlAddChild将新节点加入上层节点。

源代码文件是CreateXmlFile.cpp,如下:

/********************************************************************

created:

2007/11/09

created:

9:

11:

200715:

34

filename:

CreateXmlFile.cpp

author:

Wangxuebin

depend:

libxml2.lib

build:

nmakeTARGET_NAME=CreateXmlFile

purpose:

创建一个xml文件

*********************************************************************/

#include<stdio.h>

#include<libxml/parser.h>

#include<libxml/tree.h>

#include<iostream.h>

intmain()

{

//定义文档和节点指针

xmlDocPtrdoc=xmlNewDoc(BAD_CAST"1.0");

xmlNodePtrroot_node=xmlNewNode(NULL,BAD_CAST"root");

//设置根节点

xmlDocSetRootElement(doc,root_node);

//在根节点中直接创建节点

xmlNewTextChild(root_node,NULL,BAD_CAST"newNode1",BAD_CAST"newNode1content");

xmlNewTextChild(root_node,NULL,BAD_CAST"newNode2",BAD_CAST"newNode2content");

xmlNewTextChild(root_node,NULL,BAD_CAST"newNode3",BAD_CAST"newNode3content");

//创建一个节点,设置其内容和属性,然后加入根结点

xmlNodePtrnode=xmlNewNode(NULL,BAD_CAST"node2");

xmlNodePtrcontent=xmlNewText(BAD_CAST"NODECONTENT");

xmlAddChild(root_node,node);

xmlAddChild(node,content);

xmlNewProp(node,BAD_CAST"attribute",BAD_CAST"yes");

//创建一个儿子和孙子节点

node=xmlNewNode(NULL,BAD_CAST"son");

xmlAddChild(root_node,node);

xmlNodePtrgrandson=xmlNewNode(NULL,BAD_CAST"grandson");

xmlAddChild(node,grandson);

xmlAddChild(grandson,xmlNewText(BAD_CAST"Thisisagrandsonnode"));

//存储xml文档

intnRel=xmlSaveFile("CreatedXml.xml",doc);

if(nRel!

=-1)

{

cout<<"一个xml文档被创建,写入"<<nRel<<"个字节"<<endl;

}

//释放文档内节点动态申请的内存

xmlFreeDoc(doc);

return1;

}

编译链接命令如下:

nmakeTARGET_NAME=CreateXmlFile

然后执行可执行文件CreateXmlFile.exe,会生成一个xml文件CreatedXml.xml,打开后如下所示:

<?

xmlversion="1.0"?

>

<root>

<newNode1>newNode1content</newNode1>

<newNode2>newNode2content</newNode2>

<newNode3>newNode3content</newNode3>

<node2attribute="yes">NODECONTENT</node2>

<son>

<grandson>Thisisagrandsonnode</grandson>

</son>

</root>

最好使用类似XMLSPY这样的工具打开,因为这些工具可以自动整理xml文件的栅格,否则很有可能是没有任何换行的一个xml文件,可读性较差。

3.2解析xml文档

解析一个xml文档,从中取出想要的信息,例如节点中包含的文字,或者某个节点的属性,其流程如下:

l用xmlReadFile函数读出一个文档指针doc;

l用xmlDocGetRootElement函数得到根节点curNode;

lcurNode->xmlChildrenNode就是根节点的子节点集合;

l轮询子节点集合,找到所需的节点,用xmlNodeGetContent取出其内容;

l用xmlHasProp查找含有某个属性的节点;

l取出该节点的属性集合,用xmlGetProp取出其属性值;

l用xmlFreeDoc函数关闭文档指针,并清除本文档中所有节点动态申请的内存。

注意:

节点列表的指针依然是xmlNodePtr,属性列表的指针也是xmlAttrPtr,并没有xmlNodeList或者xmlAttrList这样的类型。

看作列表的时候使用它们的next和prev链表指针来进行轮询。

只有在Xpath中有xmlNodeSet这种类型,其使用方法前面已经介绍了。

源代码如下:

ParseXmlFile.cpp

/********************************************************************

created:

2007/11/15

created:

15:

11:

200711:

47

filename:

ParseXmlFile.cpp

author:

Wangxuebin

depend:

libxml2.lib

build:

nmakeTARGET_NAME=ParseXmlFile

purpose:

解析xml文件

*********************************************************************/

#include<libxml/parser.h>

#include<iostream.h>

intmain(intargc,char*argv[])

{

xmlDocPtrdoc;//定义解析文档指针

xmlNodePtrcurNode;//定义结点指针(你需要它为了在各个结点间移动)

xmlChar*szKey;//临时字符串变量

char*szDocName;

if(argc<=1)

{

printf("Usage:

%sdocname"n",argv[0]);

return(0);

}

szDocName=argv[1];

doc=xmlReadFile(szDocName,"GB2312",XML_PARSE_RECOVER);//解析文件

//检查解析文档是否成功,如果不成功,libxml将指一个注册的错误并停止。

//一个常见错误是不适当的编码。

XML标准文档除了用UTF-8或UTF-16外还可用其它编码保存。

//如果文档是这样,libxml将自动地为你转换到UTF-8。

更多关于XML编码信息包含在XML标准中.

if(NULL==doc)

{

fprintf(stderr,"Documentnotparsedsuccessfully."n");

return-1;

}

curNode=xmlDocGetRootElement(doc);//确定文档根元素

/*检查确认当前文档中包含内容*/

if(NULL==curNode)

{

fprintf(stderr,"emptydocument"n");

xmlFreeDoc(doc);

return-1;

}

/*在这个例子中,我们需要确认文档是正确的类型。

“root”是在这个示例中使用文档的根类型。

*/

if(xmlStrcmp(curNode->name,BAD_CAST"root"))

{

fprintf(stderr,"documentofthewrongtype,rootnode!

=root");

xmlFreeDoc(doc);

return-1;

}

curNode=curNode->xmlChildrenNode;

xmlNodePtrpropNodePtr=curNode;

while(curNode!

=NULL)

{

//取出节点中的内容

if((!

xmlStrcmp(curNode->name,(constxmlChar*)"newNode1")))

{

szKey=xmlNodeGetContent(curNode);

printf("newNode1:

%s"n",szKey);

xmlFree(szKey);

}

//查找带有属性attribute的节点

if(xmlHasProp(curNode,BAD_CAST"attribute"))

{

propNodePtr=curNode;

}

curNode=curNode->next;

}

//查找属性

xmlAttrPtrattrPtr=propNodePtr->properties;

while(attrPtr!

=NULL)

{

if(!

xmlStrcmp(attrPtr->name,BAD_CAST"attribute"))

{

xmlChar*szAttr=xmlGetProp(propNodePtr,BAD_CAST"attribute");

cout<<"getattribute="<<szAttr<<endl;

xmlFree(szAttr);

}

attrPtr=attrPtr->next;

}

xmlFreeDoc(doc);

return0;

}

编译链接命令如下:

nmakeTARGET_NAME=ParseXmlFile

执行命令如下,使用第一次创建的xml文件作为输入:

ParseXmlFile.exeCreatedXml.xml

观察源代码可发现,所有以查询方式得到的xmlChar*字符串都必须使用xmlFree函数手动释放。

否则会造成内存泄漏。

3.3修改xml文档

有了上面的基础,修改xml文档的内容就很简单了。

首先打开一个已经存在的xml文档,顺着根结点找到需要添加、删除、修改的地方,调用相应的xml函数对节点进行增、删、改操作。

源代码见ChangeXmlFile,编译链接方法如上。

执行下面的命令:

ChangeXmlFile.exeCreatedXml.xml

可以得到一个修改后的xml文档ChangedXml.xml,如下:

<?

xmlversion="1.0"?

>

<root>

<newNode2>contentchanged</newNode2>

<newNode3newAttr="YES">newNode3content</newNode3>

<node2attribute="no">NODECONTENT</node2>

<son>

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 法律文书 > 调解书

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2