libxml2在linux下的使用.docx

上传人:b****6 文档编号:5947756 上传时间:2023-01-02 格式:DOCX 页数:13 大小:25.61KB
下载 相关 举报
libxml2在linux下的使用.docx_第1页
第1页 / 共13页
libxml2在linux下的使用.docx_第2页
第2页 / 共13页
libxml2在linux下的使用.docx_第3页
第3页 / 共13页
libxml2在linux下的使用.docx_第4页
第4页 / 共13页
libxml2在linux下的使用.docx_第5页
第5页 / 共13页
点击查看更多>>
下载资源
资源描述

libxml2在linux下的使用.docx

《libxml2在linux下的使用.docx》由会员分享,可在线阅读,更多相关《libxml2在linux下的使用.docx(13页珍藏版)》请在冰豆网上搜索。

libxml2在linux下的使用.docx

libxml2在linux下的使用

  这里主要讲述libxml2在linux下的使用。

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

,由于该篇文章讲解的非常详细,我也没必要重写一遍了。

如果该篇文章早出些时候,早期开发我也不会走很多弯路了。

虽然在该篇文章出现之前我已经对libxml2较熟悉了并开发完毕,但为了备忘,现在将该篇文章作为收藏之用。

在此再次感谢这篇文章的大侠为大家整理了这篇文章^_^)

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.2  xmlChar相关函数

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

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

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

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

另外要注意,因为总是要在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*/

  xmlElementType  type;  /*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*/

  unsignedshort  line;  /*linenumber*/

  unsignedshort  extra;/*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;inodeNr;i++) 

{

nodeset->nodeTab;

}

注意,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:

2007  15:

34

  filename:

CreateXmlFile.cpp

  author:

    Wangxuebin 

  depend:

    libxml2.lib 

  build:

    nmakeTARGET_NAME=CreateXmlFile

  purpose:

  创建一个xml文件

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

#include 

#include 

#include 

#include 

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文档被创建,写入"个字节"  }

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

  xmlFreeDoc(doc);

  return1;

}

编译链接命令如下:

nmakeTARGET_NAME=CreateXmlFile

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

root>

  newNode1>newNode1contentnewNode1>

  newNode2>newNode2contentnewNode2>

  newNode3>newNode3contentnewNode3>

  node2attribute="yes">NODECONTENTnode2>

  son>

    grandson>Thisisagrandsonnodegrandson>

  son>

root>

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

3.2  解析xml文档

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

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

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

l      curNode->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:

2007  11:

47

  filename:

ParseXmlFile.cpp

  author:

    Wangxuebin 

  depend:

    libxml2.lib

  build:

    nmakeTARGET_NAME=ParseXmlFile

  purpose:

  解析xml文件

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

#include 

#include 

intmain(intargc,char*argv[])

{

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

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

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

  char*szDocName;

  if(argc    {

    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        xmlFree(szAttr);

    }

    attrPtr=attrPtr->next;

  }

  xmlFreeDoc(doc);

  return0;

}

编译链接命令如下:

nmakeTARGET_NAME=ParseXmlFile

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

ParseXmlFile.exeCreatedXml.xml

观察源代码可发现,所有以查询方式得到的xmlChar*字符串都必须使

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

当前位置:首页 > 小学教育 > 语文

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1