libxml解析XML文档.docx_第1页
libxml解析XML文档.docx_第2页
libxml解析XML文档.docx_第3页
libxml解析XML文档.docx_第4页
libxml解析XML文档.docx_第5页
已阅读5页,还剩14页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

libxml - 解析 XML 文档by Jian Lee参考XML介绍:XML 和 DOMlibxml介绍数据类型 xmlChar数据结构创建 XML 文档解析 XML 文档修改 xml 文档Xpath 处理大型 XML 文档libxml2 库函数要注意的函数读取 xml 文件xml 操作基本结构及其指针类型根节点相关函数创建子节点相关函数添加子节点相关函数属性相关函数参考1. /2. /info_detail-204.html3. /wxb_nudt/archive/2007/11/28/161340.html4. /developerworks/cn/aix/library/au-libxml2.html5. /lymons/archive/2009/03/30/37553.html6. XPath 教程XML介绍:XML 和 DOMXML是eXtensible Markup Language的缩写,它是一种可扩展性标识语言, 能够让 你自己创造标识,标识你所表示的内容。DOM全称是Document Object Model(文档 对象模型),定义了一组与平台和语言无关的接口,以便程序和脚本能够动态访问 和修改XML文档内容、结构及样式。XML创建了标识,而 DOM的作用就是告诉程序 如何操作和显示这些标识。XML将数据组织成为一棵树,DOM通过解析XML文档,为XML文档在逻辑上建立一个 树模型,树的节点是一个个的对象。这样通过操作这棵树和这些对象就可以完成 对XML文档的操作,为处理文档的所有方面提供了一个完美的概念性框架。XML 中共有12种节点类型,其中最常见的节点类型有5种:元素元素是 XML 的基本组成单元。,描述XML的基本信息。属性属性节点包含关于元素节点的信息,通常包含在元素里面,描述元素的 属性。文本包含许多文本信息或者只是空白。文档文档节点是整个文档中所有其它节点的父节点。注释注释是对相关的信息进行描述、注释。libxml介绍本文所介绍的 libxml 是针对 C 语言的一套 API 接口。其他如 ruby,python亦有对应的基于 libxml 开发的绑定库接口。数据类型 xmlChar在 libXml 中用 xmlChar 替代 char , XML 使用 UTF-8 编码的一字节字符串。如 果你的数据使用其它编码,它必须被转换到 UTF-8 才能使用libxml的函数。如同标准 C 中的 char 类型一样, xmlChar 也有动态内存分配、字符串操作等 相关函数。例如 xmlMalloc 是动态分配内存的函数; xmlFree 是配套的释放内 存函数; xmlStrcmp 是字符串比较函数等等。基本上 xmlChar 字符串相关函数 都在xmlstring.h 中定义;而动态内存分配函数在 xmlmemory.h 中定义。另外要 注意,因为总是要在 xmlChar* 和 char* 之间进行类型转换,所以定义了一个宏BAD_CAST ,其定义如下: xmlstring.h#define BAD_CAST (xmlChar *)原则上来说, unsigned char 和 char 之间进行强制类型转换是没有问题的。数据结构xmlDoc代表DOM结构中的文档类型。包含由解析文档建立的树结构,xmlDocPtr 是指向这个结构的指针。xmlNode代表DOM结构中的除文档类型类型外的其它节点类型。包含单一结点 的结构, xmlNodePtr 是指向这个结构的指针,它被用于遍历文档树。节点应 该是xml中最重要的元素了, xmlNode 代表了xml文档中的一个节点,实现为一 个 struct ,内容很丰富: tree.htypedef 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 */;可以看到,节点之间是以链表和树两种方式同时组织起来的,next和prev指针可 以组成链表,而parent和children可以组织为树。所有节点都是文档 xmlDoc 节 点的直接或间接子节点。同时还有以下重要元素: 节点中的文字内容: content ; 节点所属文档: doc ; 节点名字: name ; 节点的 namespace: ns ; 节点属性列表: properties ;xml 文档的操作其根本原理就是在节点之间移动、查询节点的各项信息,并进行 增加、删除、修改的操作。 xmlDocSetRootElement 函数可以将一个节点设置为 某个文档的根节点,这是将文档与节点连接起来的重要手段,当有了根结点以 后,所有子节点就可以依次连接上根节点,从而组织成为一个 xml 树。创建 XML 文档创建一个 XML 文档流程如下:1. 用 xmlNewDoc 函数创建一个文档指针 doc;2. 用 xmlNewNode 函数创建一个节点指针 root_node;3. 用 xmlDocSetRootElement 将 root_node 设置为 doc 的根节点;4. 给 root_node 添加一系列子节点,并设置字节点的内容和属性;5. 用 xmlSaveFile 保存 xml 到文件;6. 用 xmlFreeDoc 函数关闭文档指针,清除内存。示例下面用一个例子说明一些函数的使用,和创建一个 XML 文档的大致步骤:#include #include #include #include int main (int argc, char *argv) xmlDocPtr pdoc = NULL; xmlNodePtr proot_node = NULL,pnode = NULL,pnode1 = NULL; / 创建一个新文档并设置 root 节点 / 一个 XML 文件只有一个 root 节点 pdoc = xmlNewDoc (BAD_CAST 1.0); proot_node = xmlNewNode (NULL, BAD_CAST 根节点); xmlNewProp (proot_node, BAD_CAST 版本, BAD_CAST 1.0); xmlDocSetRootElement (pdoc, proot_node); pnode = xmlNewNode (NULL, BAD_CAST 子节点1); / 创建上面 pnode 的子节点 xmlNewChild (pnode, NULL, BAD_CAST 子子节点1, BAD_CAST 信息); / 添加子节点到 root 节点 xmlAddChild (proot_node, pnode); pnode1 = xmlNewNode (NULL, BAD_CAST 子子节点1); xmlAddChild (pnode, pnode1); xmlAddChild (pnode1,xmlNewText (BAD_CAST 这是更低的节点,子子子节点1); / 还可以这样直接创建一个子节点到 root 节点上 xmlNewTextChild (proot_node, NULL, BAD_CAST 子节点2, BAD_CAST 子节点2的内容); xmlNewTextChild (proot_node, NULL, BAD_CAST 子节点3, BAD_CAST 子节点3的内容); / 保存 xml 为文件,如果没有给出文件名参数,就输出到标准输出 xmlSaveFormatFileEnc (argc 1 ? argv1:-, pdoc, UTF-8, 1); / 释放资源 xmlFreeDoc (pdoc); xmlCleanupParser (); xmlMemoryDump (); return 0;编译这个例子,先看看系统里面的 libxml2 库的 pkgconfig 信息:rootjianlee:/lab/xml# cat /usr/lib/pkgconfig/libxml-2.0.pcprefix=/usrexec_prefix=$prefixlibdir=$exec_prefix/libincludedir=$prefix/includemodules=1Name: libXMLVersion: 2.6.32Description: libXML library version2.Requires:Libs: -L$libdir -lxml2Libs.private: -lz -lmCflags: -I$includedir/libxml2rootjianlee:/lab/xml# pkg-config libxml-2.0 -cflags -libs-I/usr/include/libxml2 -lxml2编译:rootjianlee:/lab/xml# gcc -Wall pkg-config libxml-2.0 -cflags -libs create_xml.c如果没有修改源程序,输出应该是这样:rootjianlee:/lab/xml# ./a.out 信息 这是更低的节点,子子子节点1 子节点2的内容 子节点3的内容示例补充说明输出的各节点不要在一行上面使用下面方式保存 xml 文档,输出的文件各子节点间自动加入回车: / 保存 xml 为文件,如果没有给出文件名参数,就输出到标准输出 xmlSaveFormatFileEnc (argc 1 ? argv1:-, pdoc, UTF-8, 1);如果把上面的 1 换成 0 ,输出格式是放在一行。用到的函数说明上面涉及几个函数和类型定义,不过意思很明了,下面解释一个(重要的是自己 动手写程序,反复实验,所谓熟能生巧)。xmlDocPtr指向 XML 文档对象的指针xmlNodePtr指向 XML 文档对象中的节点对象(根节点和子节点都是一样的)xmlNewDoc创建一个 XML 文档对象xmlNewNode创建一个 XML 文档的指针对象xmlNewProp给一个节点增加属性信息,包括在 中,如: xmlNewProp (proot_node, BAD_CAST 版本, BAD_CAST 1.0);最后显示是这个样子:xmlDocSetRootElement设置 XML 文档对象的根节点,只有一个根节点xmlNewChild指定一个节点,会创建这个节点的子节点。这样不需要使用xmlNewNode 创建一个节点,再使用 xmlAddChild 添加到其父节点中。xmlAddChild把一个节点设置为另外一个节点的子节点。xmlNewText创建一个描述节点,没有 符号,需要添加到其他节点上。比 如上例中的: xmlAddChild (pnode1,xmlNewText (BAD_CAST 这是更低的节点,子子子节点1);会出现下面的结果: 这是更低的节点,子子子节点1xmlNewTextChild和 xmlNewText 的区别如同 xmlNewNodeChild 和xmlNewNode 的区别一样!xmlSaveFormatFileEnc保存 xml 对象为文件。xmlFreeDoc释放 xml 对象xmlCleanupParser清理xmlMemoryDump清理解析 XML 文档解析一个xml文档,从中取出想要的信息,例如节点中包含的文字,或者某个节点 的属性,其流程如下: 用 xmlReadFile 函数读出一个文档指针 doc ; 用 xmlDocGetRootElement 函数得到根节点 curNode ; curNode-xmlChildrenNode 就是根节点的子节点集合 ; 轮询子节点集合,找到所需的节点,用 xmlNodeGetContent 取出其内容 ; 用 xmlHasProp 查找含有某个属性的节点 ; 取出该节点的属性集合,用 xmlGetProp 取出其属性值 ; 用 xmlFreeDoc 函数关闭文档指针,并清除本文档中所有节点动态申请的内存。注意: 节点列表的指针依然是 xmlNodePtr ,属性列表的指针也是 xmlAttrPtr,并没有 xmlNodeList 或者 xmlAttrList 这样的类型 。看作列表的时候使用它 们的 next 和 prev 链表指针来进行轮询 。只有在 Xpath 中有 xmlNodeSet 这 种类型。示例#include #include #include #include int main (int argc , char *argv) xmlDocPtr pdoc = NULL; xmlNodePtr proot = NULL, curNode = NULL; char *psfilename; if (argc name, BAD_CAST 根节点) != 0) printf (错误文档 ); exit (1); /* 如果打开的 xml 对象有 version 属性,那么就输出它的值。 */ if (xmlHasProp (proot, BAD_CAST 版本) xmlChar *szAttr = xmlGetProp (proot, BAD_CAST 版本); printf (版本: %s n根节点:%sn , szAttr, proot-name); else printf ( xml 文档没有版本信息n); curNode = proot-xmlChildrenNode; char n=0; while (curNode != NULL) if (curNode-name != BAD_CAST text) printf (子节点%d: %sn, n+,curNode-name); curNode = curNode-next; /* 关闭和清理 */ xmlFreeDoc (pdoc); xmlCleanupParser (); return 0;编译运行(使用上例创建的 my.xml 文件):rootjianlee:/lab/xml# cat my.xml 信息 这是更低的节点,子子子节点1 子节点2的内容 子节点3的内容rootjianlee:/lab/xml# gcc -Wall pkg-config libxml-2.0 -cflags -libs read_xml.crootjianlee:/lab/xml# ./a.out my.xml版本: 1.0根节点:根节点子节点0: text子节点1: 子节点1子节点2: text子节点3: 子节点2子节点4: text子节点5: 子节点3子节点6: text为什么 my.xml 文件中显示只有 ”子节点1“、 ”子节点2“和 “子节点3”三个子节 点,而程序显示有 7 个子节点呢?!而且 0、2、4、6 都是 text 名字?这是因为其他四个分别是元素前后的空白文本符号,而 XML 把它们也当做一个Node !元素是 Node 的一种类型。XML 文档对象模型 (DOM) 定义了几种不同的Nodes 类型,包括 Elements(如 files 或者 age)、Attributes(如 units) 和 Text(如 root 或者 10)。元素可以具有子节点。在打开 xml 文档之前加上一句(取消上面程序中的此句注释就可以): xmlKeepBlanksDefault(0);或者使用下面参数读取 xml 文档:/读取xml文件时忽略空格doc = xmlReadFile(docname, NULL, XML_PARSE_NOBLANKS);这样就可以按我们所想的运行了:rootjianlee:/lab/xml# gcc -Wall pkg-config libxml-2.0 -cflags -libs read_xml.crootjianlee:/lab/xml# ./a.out my.xml版本: 1.0根节点:根节点子节点0: 子节点1子节点1: 子节点2子节点2: 子节点3还有一点注意: my.xml 文件中的子节点名字一次是 “子节点1”、“子节点2”、“子节点3”。程序中的 n 值确是从 0 开始计算。从 0 还是 1 是个人喜好。我有 时候喜好从 0 开始,有时候喜好从 1 开始。xmlFreeDoc释放文档指针。特别注意,当你调用 xmlFreeDoc 时,该文档所 有包含的节点内存都被释放,所以一般来说不需要手动调用 xmlFreeNode 或者xmlFreeNodeList 来释放动态分配的节点内存,除非你把该节点从文档中移除 了。一般来说,一个文档中所有节点都应该动态分配,然后加入文档,最后调 用 xmlFreeDoc 一次释放所有节点申请的动态内存,这也是为什么我们很少看 见 xmlNodeFree 的原因。xmlSaveFile将文档以默认方式存入一个文件。xmlSaveFormatFileEnc可将文档以某种编码/格式存入一个文件中,创建 xml文档是的示例中用到修改 xml 文档首先打开一个已经存在的xml文档,顺着根结点找到需要添加、删除、修改的地 方,调用相应的xml函数对节点进行增、删、改操作。删除节点删除节点使用下面方法:if (!xmlStrcmp(curNode-name, BAD_CAST newNode1) xmlNodePtr tempNode; tempNode = curNode-next; xmlUnlinkNode(curNode); xmlFreeNode(curNode); curNode = tempNode; continue; 即将当前节点从文档中断链(unlink),这样本文档就不会再包含这个子节点。 这样做需要使用一个临时变量来存储断链节点的后续节点,并记得要手动删除断 链节点的内存。示例#include #include #include int main(int argc, char* argv) xmlDocPtr doc; /定义解析文档指针 xmlNodePtr curNode; /定义结点指针(你需要它为了在各个结点间移动) char *szDocName; if (argc children; while (NULL != curNode) /删除 子节点1 if (!xmlStrcmp(curNode-name, BAD_CAST 子节点1) xmlNodePtr tempNode; tempNode = curNode-next; xmlUnlinkNode(curNode); xmlFreeNode(curNode); curNode = tempNode; continue; /修改 子节点2 的属性值 if (!xmlStrcmp(curNode-name, BAD_CAST 子节点2) xmlSetProp(curNode,BAD_CAST 属性1, BAD_CAST 设置); /修改 “子节点2” 的内容 if (!xmlStrcmp(curNode-name, BAD_CAST 子节点2) xmlNodeSetContent(curNode, BAD_CAST 内容变了); /增加一个属性 if (!xmlStrcmp(curNode-name, BAD_CAST 子节点3) xmlNewProp(curNode, BAD_CAST 新属性, BAD_CAST 有); /增加 子节点4 if (!xmlStrcmp(curNode-name, BAD_CAST 子节点3) xmlNewTextChild(curNode, NULL, BAD_CAST 新子子节点1, BAD_CAST 新内容); curNode = curNode-next; / 保存文件 xmlSaveFormatFileEnc (szDocName, doc,UTF-8,1); xmlFreeDoc (doc); xmlCleanupParser (); xmlMemoryDump (); return 0;编译运行:rootjianlee:/lab/xml# cat my.xml 信息 这是更低的节点,子子子节点1 子节点2的内容 子节点3的内容rootjianlee:/lab/xml# gcc -Wall pkg-config libxml-2.0 -cflags -libs modify_xml.crootjianlee:/lab/xml# ./a.out my.xmlrootjianlee:/lab/xml# cat my.xml 内容变了 子节点3的内容新内容rootjianlee:/lab/xml# ./a.out my.xml # 看看再运行一次的结果!rootjianlee:/lab/xml# cat my.xml 内容变了 子节点3的内容新内容新内容Xpath 处理大型 XML 文档libxml2 库函数要注意的函数xmlKeepBlanksDefaultint xmlKeepBlanksDefault (int val)设置是否忽略空白节点,比如空格,在分析前必须调用,默认值是0,最好设置成1.xmlKeepBlanksDefault(0) 除了在读入xml文件时忽略空白之外,还会在写出xml文件时在每行前面放置缩进(indent)。如果使用xmlKeepBlanksDefault(1) 则 你会发现每行前面的缩进就没有了,但不会影响回车换行。xmlSaveFormatFile / 保存 xml 为文件,如果没有给出文件名参数,就输出到标准输出 xmlSaveFormatFileEnc (argc 1 ? argv1:-, pdoc, UTF-8, 1);xmlSaveFormatFile 的 format 参数设置成 0,保存后的 xml 文档里是会把所有 的结点都放到一行里显示。设置为 1,就可以自动添加回车。读取 xml 文件xmlParseFilexmlDocPtr xmlParseFile (const char * filename)以默认方式读入一个 UTF-8 格式的 xml 文档, 并返回一个文档对象指针xmlReadFile指定编码读取一个 xml 文档,返回指针。xml 操作基本结构及其指针类型xmlDoc, xmlDocPtr文档对象的结构体及其指针xmlNode, xmlNodePtr节点对象的结构体

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论