1、简介如果您在 IBM 操作系统下编写过程序,那么肯定听说过 Rexx。Rexx 是 IBM 随其大型主机、中型操作系统和更低端操作系统一起捆绑的脚本和命令语言。您可能不清楚的是,Rexx 几乎可以在世界上各种其他的操作系统上运行。您可以免费下载用于各版本的 Windows、Linux、UNIX、BSD、Mac OS 和 DOS 以及很多其他系统的 Rexx。它甚至可以在用于手持设备的三大主流操作系统 Windows CE、Palm OS 和 Symbian/EPOC32 上运行。 这意味着,如果您学习 Rexx,就可以知道一种可以在从大型主机到手持设备的各种地方运行的脚本语言。Rexx 是一种
2、通用的语言,它强大得足以适合大型主机,但是又灵活得足以适合其他平台。最棒的是,Rexx 容易学习。在本文中,我将对 Rexx 作一个简要的介绍,作为使用它访问 IBM DB2 UDB 数据的基础。(在后续的文章中,我将给出并讨论更多的 Rexx 脚本示例,以便更深入地解释如何专门为 DB2 应用程序编写 Rexx 脚本。)我将对 Rexx 语言进行概述,并展示学习 Rexx 语言是多么的容易。我还将描述很多可用的免费和开放源码的 Rexx 解释器,并告诉您在哪里可以下载这些解释器。最重要的是,我将为您指出 Web 上提供的其他免费信息来源(参阅参考资料)。在几天时间内,您可以学习使用 Rexx
3、 编程,Rexx 是一种脚本语言,适用于几乎任何编程问题,并且几乎可以在任何机器上运行。快速了解 Rexx您已经知道 Rexx 容易学习,那么现在就来验证一下吧。下面是一个完整的 Rexx 脚本:input = invoice_file.txt/* Name the input file */do whilelines(input) 0/* Do while lines to read */ input_line = linein(input) /* Read in the next line */ if pos(INVOICE OVERDUE, input_line) 0 thensay F
4、ound it!Heres where:input_line elsesay Not found in this line: input_lineend这个脚本从一个输入文件读取所有的行,每次读取一行,并扫描各行,以发现短语 INVOICE OVERDUE。如果该脚本发现了这个短语,则写出一条消息以及短语所在的行。它还通过一条合适的 not found 消息显示被排除的行。在该脚本中,第一行将输入文件的名称(这里是 invoice_file.txt)赋给一个名为 input 的变量。这是一个简单的赋值语句,与大多数编程语言中的一样。在 Rexx 中,赋给变量的字符串或文字可以用单引号或双引号括
5、起来:input = invoice_file.txt /* Name the input file*/接下来的 do while 循环逐行处理输入文件中的输入行。它使用内置的 lines 函数来判断在输入文件中是否还有未读到的行。如果没有剩下要读的行,则 lines 函数返回 0:do while lines(input) 0/* Do while there are lines to read*/在 Rexx 中,所有内置函数都很容易识别,因为这些函数后面都会紧跟着括号,括号中包含函数的输入参数。函数与紧随的左括号之间不能有空格。前面的语句表明,lines 函数只带有一个参数,该参数就是它
6、将测试其 end of file 的文件的名称。记住,在我们的脚本中,变量 input 指的是名为 invoice_file.txt 的输入文件。现在便到了程序的核心。这一行使用 Rexx 的 pos 内置函数来判断输入行是否包含字符串 INVOICE OVERDUE:if pos(INVOICE OVERDUE, input_line) 0 thenpos 函数返回 INVOICE OVERDUE 在给定行中出现的位置。或者,如果在行中没有找到该短语,则返回 0。这条语句中的测试让该脚本写一行文本到显示屏幕上,表明字符串 INVOICE OVERDUE 是否存在于输入行中。然后,Rexx 的
7、 say 指令写输出行。在我们的例子中,say 指令有两个操作对象。第一个操作对象是用引号括起来的一个字符串文字,第二个操作对象是包含文件中当前行的变量。say 指令可以带任意个操作对象,它会自动将这些操作对象连接在一起,并将它们发送到用户的显示屏幕: if pos(INVOICE OVERDUE, input_line) 0 thensay Found it!Heres where:input_line elsesay Not found in this line: input_line好了。您已经看到了一个完整的 Rexx 脚本。从中可以看出,Rexx 在语法方面要求很少,而且没有“专用字
8、符”。这是不是使之成为容易的语言的原因呢?Rexx 为什么容易我给出的简单脚本演示了 Rexx 的易用性。例如,它表明您不需要声明或预定义程序变量。您可以在任何时候、任何地方直接引用一个新的变量,Rexx 会定义这个变量。例如,程序中的第一行通过给变量 input 赋一个值自动定义该变量。在使用这个变量之前,不需要声明或预定义该变量。同样也不需要声明变量的数据类型。在 Rexx 中,所有变量都是无类型的。而且,变量包含可变长度的字符串,变量的内容便定义了变量的类型。如果您将一个看上去像是数值的字符串赋给一个变量,那么 Rexx 将允许您在此变量上执行计算。如果将一个字符串赋给一个变量,那么 R
9、exx 将允许您在此变量上执行字符串操作(例如解析、模式匹配或并置)。有些语言要求预定义变量,并指定变量的“数据类型”,而 Rexx 则通过变量的内容和使用情况动态地定义变量。必要时,Rexx 透明地转换数据,并且将很多细节工作自动化,这一点把使用其他语言的程序员吸引了过来。下面是一个简单的例子:a = 3/* Create a numeric variable */b = 4/* This string value also represents a number*/saya + b /* Displays the numeric result:7 */saya|b/* Concatenat
10、e the two strings together */*Displays:34*/c = Hi!/* Create variable that is a character string*/saya+c /* This results in error!You can not */ /* add a character value to a number */-SYNTAX:Bad arithmetic conversion (error 41)该代码首先创建两个变量,这两个变量包含表示数的值。(在 Rexx 中,数 是由数字组成的任何串,中间可以包含小数点,前面还可以有符号。数还可以用科
11、学或工程计数法中的指数形式表达。)第三条语句展示了两个数的相加,第四条语句表明这两个变量还可以看作是由单个数字组成的字符串。第四条语句通过并置操作符 | 将两个字符串(恰好是由数字组成的字符串)并置或粘贴在一起。最后两行表明,虽然 Rexx 可以随时自动执行转换,但它不允许将非数字字符串与一个数相加。在计算中,只有包含数值的变量才可以看作数。让我们回到最初的那个例子:扫描字符串 INVOICE OVERDUE 的脚本。注意,该脚本不打开它的输入文件。文件很像是变量,在使用之前无需显式地定义它们 您可以直接开始读或写文件。同样,程序在使用文件之后不必关闭文件,因为当程序终止时文件会自动关闭。我也
12、没有正式地结束该脚本(您可以编写一个 Rexx 出口指令来结束 Rexx 代码,但这不是必需的)。Rexx 除了为您执行这些隐式操作之外,Rexx 还很容易,因为它是一种格式自由的语言。您可以随意使用空格、空白行和缩进。作为一个简单的例子,您也可以像下面这样来编写 if 语句,而结果是一样的: if pos(INVOICE OVERDUE, input_line) 0then say Found it!Heres where:input_lineelse say Not found in this line: input_line就格式而言,Rexx 是编程语言中最为宽松的。而且,它不是大小写
13、敏感的。它的指令、函数和变量可以用大写、小写或大小写混合的形式编写。例如,您也可以将变量名 input_line 写为 INPUT_LINE、Input_Line 或 Input_line;对于 Rexx 来说这都是一样的。还有一种编写 if 语句的方法,即使用大小写将 Rexx 指令和函数与语句的其他部分区分开来:IF POS(INVOICE OVERDUE, Input_Line) 0 THEN SAY Found it! Heres where: Input_Line ELSE SAY Not found in this line: Input_LineRexx 为什么强大除了它的易用性
14、外,Rexx 的基本设计使得它成为一种强大的语言。如 图 1 所示,Rexx 有大约 20 条指令作为一个小小的核心。这个核心周围有大约 70 个内置函数。这样一来,基础的东西很容易学习,然后又可以逐渐增长函数方面的知识。这同时也意味着 Rexx 的强大性。除了内置函数外,Rexx 脚本很容易访问免费的外部函数库、工具和接口。这涉及每种能想像到的接口,包括数据库访问、图形用户界面、XML、Web 服务器编程、图、 MIDI 接口、Windows Registry 更新、语音合成以及 Apache 编程 只要您提供名称,Rexx 就能访问。图 1. Rexx 的组成Rexx 之所以强大,很大程度
15、上是因为它是一种“胶水”语言。Rexx 脚本容易发出操作系统命令。因此,数年前 IBM 就选择 Rexx 作为用于其大型主机和其他操作系统的“命令过程语言”。Rexx 将现有的代码粘合在一起 不管代码的形式是操作系统命令、界面 API、服务、小配件、对象、函数、接口还是工具 并利用这一点获得更大的生产率。这就是 Rexx 之类的脚本语言比传统的、需要编译的编程语言(如 C+、C、COBOL 或 Java)要强大得多的原因。虽然这些语言通过一定的努力也可以发出操作系统命令以及使用一般的接口,但 Rexx 之类的脚本语言是专门为此而设计的。Rexx 最强大的特性之一是数组(在其他编程语言中有时候也
16、称为表)的实现。使数组强大的原因是,数组不但可以通过数字下标索引,而且还可以用字符串作为数组的下标。因此,数组支持所谓的按内容寻址的存储器或关联存储器。这使得 Rexx 数组的威力远远超出了编程语言中表的威力,后者只支持数字下标。例如,数组可以支持字典查询,并为高级类型的数据结构,例如键-值对、链接表、双链表和树形成基础。数组是将变量与值以对程序最有意义的任何方式相关联的常用手段,所以更应该将它们称作复合变量。Rexx 特性接下来,我将简要地描述 Rexx 的一些其他特性。该语言包括一组完整的指令,用于控制程序逻辑(例如 do、do while、if、if-then-else、select、c
17、all、return 和 exit)。它支持结构化程序设计 和模块性,这是作为广为接受的程序设计最佳实践的原则。但是 Rexx 是一种强大的语言,包括用于非结构化逻辑的指令,在少数情况下需要用到这些指令。这些指令包括 iterate、leave、do until、do forever 和 signal (大致类似于其他语言中的 goto)。 我曾提到,Rexx 包含 70 多个内置函数。这些函数分为字符串操作、位操作、数字、输入/输出、转换、环境和杂项等类别。Rexx 脚本像调用内置函数或用户编写的函数一样调用外部函数(假设已建立到外部函数库的连接)。所以,当使用外部函数库或附加函数库时,Re
18、xx 代码像对待该语言的内置特性一样引用那些函数。与大多数解释器一样,Rexx 支持交互式调试。您可以运行一个脚本,在任何时候停止它,检查脚本的变量,甚至重新运行代码或者修改代码。Rexx 内置的调试器使得发现和修复逻辑错误非常容易。交互式调试通常被认为比批模式调试更好(Rexx 也支持批模式调试)。Rexx 还包括一个异常或错误处理程序。这可以为很多常见的错误条件(例如语法错误或算术上溢)设陷,并将控制流转移到您自己编写的一个专门的错误处理例程。异常设陷提供了通过一个单独的例程来管理常见错误的标准方式。Rexx 还支持一种名为外部数据队列(external data queue) 的通信机制
19、,但是通常被简单地称为栈。作为 Rexx 独有的一个强大特性,栈为 Rexx 例程或程序之间的通信提供了手段。取决于主机操作系统和 Rexx 解释器,栈支持相同机器上不同程序甚至不同机器上的不同程序之间的通信。这包括跨 Internet 的远程通信。当然,Rexx 脚本还可以采用更传统的通信手段,例如 TCP/IP、FTP、套接字和管道。最后,我应该提到 Rexx 脚本的可移植性。Rexx 有一个较强的语言标准,本文提到的所有解释器都遵从这个标准。这不仅使 Rexx 技巧可以转移,而且表明这种脚本是可移植的。有了标准 Rexx 脚本,您可以很容易地将它在 Linux、Windows、大型主机、
20、手持设备之间移植。如果脚本发出特定于操作系统的命令,那么 Rexx 会提供一些免费的、跨平台接口来缓冲脚本对平台的依赖。下载免费的 Rexx我曾提到,Rexx 是和所有 IBM 操作系统捆绑在一起的。此外,您可以下载免费的或开放源码的用于任何操作系统的 Rexx。一共有 8 种免费或开放源码 Rexx 解释器。每种解释器都符合 Rexx 标准,所以您的 Rexx 技巧适用于所有这些解释器,并且 Rexx 脚本在上述任意解释器下均可运行。这些解释器之间的不同之处在于它们所支持的平台以及所提供的额外的东西。例如,有些解释器在手持设备上运行,其他一些解释器提供了特定于操作系统的语言扩展,其他解释器支
21、持完全面向对象的编程。下面是 6 个免费的 Rexx 解释器的概述: Rexx 解释器 解释器平台简介Regina所有主流操作系统最流行的 Rexx 解释器。它拥有很大的用户社区,这意味着可以获得广泛的支持,而且它完全使用免费的工具和接口。它附带了很多额外的内置函数以及非常好的、专业的文档。如果您刚接触 Rexx,那么我建议从 Regina 开始。Rexx/imcLinux、UNIX、BSD这是面向 UNIX 和 Linux 的解释器,包括用于这两种环境的扩展。它长期提供良好的支持。BRexx Linux、UNIX、Windows CE、Mac OS、16 位和 32 位 DOS 及其他这种非
22、常快的解释器占用内存很少,可以在很多平台上运行,包括资源受限的系统,例如 Windows CE、嵌入式 Linux 和 DOS。它提供了很多额外的函数及接口,并长期提供良好的支持。Reginald WindowsReginald 为 Windows 程序员定制和扩展 Rexx。它易于使用,并且包括很多 Windows 工具,例如一个 GUI、语音、MIDI 和媒体函数。Reginald 为诸如 VBScript 之类的专用工具提供了一种标准的语言方案,并提供了包含示例在内的良好文档。r4 Windowsr4 扩展了用于 Windows 的 Rexx,提供了很多工具,包括一个 GUI 窗体工具、
23、彩色的文本文件浏览器和编辑器、超过 135 种 Windows 命令工具、XML 到 HTML 的自动转换器、GUI 小配件,等等。它还包括很好的教程以及示例脚本。用于 Palm OS 的 Rexx Palm OS这种解释器通过脚本将 Palm OS 应用程序与数据库粘合在一起,脚本无需离开当前的应用程序便可运行。这些脚本可以访问所有的 Palm 数据和资源,包括 TCP/IP、红外线、USB 和串行通信、控制台、剪切板等。它在本地运行,带有易于遵循的教程,其中包含很好的示例脚本。除了这些标准的过程 Rexx 解释器以外,还有两种面向对象的 Rexx 解释器。它们是完全面向对象的语言,带有完整
24、而强大的类库。它们支持所有 OOP 原理,包括类继承、继承、多重继承、封装、抽象和多态。这两种产品都是标准的过程 Rexx 的超集,所以通过使用标准 Rexx 特性和函数便可以立即开始用它们来编程,然后逐渐涉及面向对象特性。此外,标准的 Rexx 脚本可以不作修改地在这两种解释器下运行: 面向对象 Rexx 解释器 解释器平台简介Open Object Rexx Windows、Linux、UNIX这是传统 Rexx 的完全面向对象的超集。它由 IBM 开发,在 2004 年末成为开放源码的。现在它由 Rexx Language Association 升级和维护,是最广泛使用的面向对象 Re
25、xx 解释器。roo! Windowsroo! 也是传统 Rexx 的完全面向对象的超集。它与标准 r4 Rexx 解释器来自相同的公司,附带了同样丰富的 Windows 工具。它还包括简洁易懂的教程,帮助理解标准 Rexx 编程与面向对象 Rexx 编程之间的差异。最后要提到的是,还有一种用于 Java 环境的 Rexx,即 NetRexx。在本文中讨论的所有 Rexx 解释器当中,只有这种解释器不符合 Rexx 语言标准 所以称其为“类 Rexx”最为恰当。这种解释器的作用是将 Rexx 的易用性带入到 Java 环境。NetRexx 脚本使用 Java 类,它们可以通过 Java 脚本创
26、建 Java 类。NetRexx 允许编写 applet、应用程序和 servlet,而不会与 Java 中继承于 C 的语法发生冲突。您甚至可以使用它来创建 Java Beans 和生成带有完整注释的 Java 代码。NetRexx 同时支持客户端和服务器端脚本,可以在任何 Java 虚拟机(JVM)上运行。接下来的内容在我接下来的文章中,我将更多地涉及 Rexx 编程的技术方面,并提供一些实用的编程示例。这些示例脚本将演示如何使用 Rexx 作为快速开发访问 DB2 UDB 数据的程序的工具。除了传授更多关于 Rexx 脚本编制的知识外,还将提供相应的实用数据库示例。我将采用 Regina
27、 Rexx 解释器,它为示例脚本访问 Windows 服务器上的 DB2 UDB。但是我要使用的 Rexx 和数据库接口都可以在 Linux、UNIX 和其他操作系统之间移植。使用像 Rexx 这样的开放源码语言的一大好处是,可以随处找到很多免费的相关参考资料(参阅 参考资料)。 开放源码/免费软件运动是我们这个时代伟大的技术传奇之一。当今另一个大趋势就是脚本编制。Rexx 立足于这两大趋势的交叉点。它提供了一种免费的、易于使用的、强大的、标准化的通用脚本语言。有了它,就可以快速地为各种不同问题编写程序,并且成本很低。尽情编写脚本吧!附录资料:不需要的可以自行删除 libxml2应用实例Lib
28、xml2 是一个xml的c语言版的解析器,本来是为Gnome项目开发的工具,是一个基于MIT License的免费开源软件。它除了支持c语言版以外,还支持c+、PHP、Pascal、Ruby、Tcl等语言的绑定,能在Windows、Linux、Solaris、MacOsX等平台上运行。功能还是相当强大的,相信满足一般用户需求没有任何问题。二、 Libxml2安装:一般如果在安装系统的时候选中了所有开发库和开发工具的话(Fedora Core系列下),应该不用安装,下面介绍一下手动安装: 1) 从xmlsoft站点或ftp(ftp.xmlsoft.org)站点下载libxml压缩包(libxml
29、2-xxxx.tar.gz)2) 对压缩包进行解压缩 tar xvzf libxml2-xxxx.tar.gz3) 进入解压缩后的文件夹中运行 ./configure -prefix /home/user/myxml/xmlinst(此处为待安装的路径)或者直接使用 ./configure make make install 4) 添加路径 export PATH=/home/user/myxml/xmlinst/bin:$PATH 说明:为了结构清晰,最好将libxml2不安装在解压目录中。安装完成后就可以使用简单的代码解析XML文件,包括本地和远程的文件,但是在编码上有一些问题。Libxm
30、l默认只支持UTF8的编码,无论输入输出都是UTF-8,所以如果你解析完一个XML得到的结果都是UTF8的,如果需要输出GB2312或者其它编码,需要ICONV来做转码(生成UTF8编码的文件也可以用它做),如果系统中没有安装iconv的话,需要安装libiconv。 1) 下载libiconv压缩包(例如libiconv-1.11.tar.gz) 2) 对压缩包进行解压缩tar xvzf libiconv-1.11.tar.gz 3) 进入解压缩后的文件夹中运行 ./configure make make install三、关于XML:在开始研究 Libxml2 库之前,先了解一下XML的相
31、关基础。XML 是一种基于文本的格式,它可用来创建能够通过各种语言和平台访问的结构化数据。它包括一系列类似 HTML 的标记,并以树型结构来对这些标记进行排列。例如,可参见清单 1 中介绍的简单文档。为了更清楚地显示 XML 的一般概念,下面是一个简化的XML文件。清单 1. 一个简单的 XML 文件 root delete 10清单 1 中的第一行是 XML 声明,它告诉负责处理 XML 的应用程序,即解析器,将要处理的 XML 的版本。大部分的文件使用版本 1.0 编写,但也有少量的版本 1.1 的文件。它还定义了所使用的编码。大部分文件使用 UTF-8,但是,XML 设计用来集成各种语言
32、中的数据,包括那些不使用英语字母的语言。接下来出现的是元素。一个元素以开始标记 开始(如 ),并以结束标记 结束(如 ),其中使用斜线 (/) 来区别于开始标记。元素是 Node 的一种类型。XML 文档对象模型 (DOM) 定义了几种不同的 Nodes 类型,包括:Elements(如 files 或者 age)Attributes(如 units)Text(如 root 或者 10)元素可以具有子节点。例如,age 元素有一个子元素,即文本节点 10。XML 解析器可以利用这种父子结构来遍历文档,甚至修改文档的结构或内容。LibXML2 是这样的解析器中的其中一种,并且文中的示例应用程序正
33、是使用这种结构来实现该目的。对于各种不同的环境,有许多不同的解析器和库。LibXML2 是用于 UNIX 环境的解析器和库中最好的一种,并且经过扩展,它提供了对几种脚本语言的支持,如 Perl 和 Python。四、Libxml2中的数据类型和函数一个函数库中可能有几百种数据类型以及几千个函数,但是记住大师的话,90%的功能都是由30%的内容提供的。对于libxml2,我认为搞懂以下的数据类型和函数就足够了。1)内部字符类型xmlCharxmlChar是Libxml2中的字符类型,库中所有字符、字符串都是基于这个数据类型。事实上它的定义是:xmlstring.htypedef unsigned
34、 char xmlChar;使用unsigned char作为内部字符格式是考虑到它能很好适应UTF-8编码,而UTF-8编码正是libxml2的内部编码,其它格式的编码要转换为这个编码才能在libxml2中使用。还经常可以看到使用xmlChar*作为字符串类型,很多函数会返回一个动态分配内存的xmlChar*变量,使用这样的函数时记得要手动删除内存。2) xmlChar相关函数如同标准c中的char类型一样,xmlChar也有动态内存分配、字符串操作等相关函数。例如xmlMalloc是动态分配内存的函数;xmlFree是配套的释放内存函数;xmlStrcmp是字符串比较函数等等。基本上xml
35、Char字符串相关函数都在xmlstring.h中定义;而动态内存分配函数在xmlmemory.h中定义。3)xmlChar*与其它类型之间的转换另外要注意,因为总是要在xmlChar*和char*之间进行类型转换,所以定义了一个宏BAD_CAST,其定义如下:xmlstring.h#define BAD_CAST (xmlChar *)原则上来说,unsigned char和char之间进行强制类型转换是没有问题的。4)文档类型xmlDoc、指针xmlDocPtrxmlDoc是一个struct,保存了一个xml的相关信息,例如文件名、文档类型、子节点等等;xmlDocPtr等于xmlDoc*
36、,它搞成这个样子总让人以为是智能指针,其实不是,要手动删除的。xmlNewDoc函数创建一个新的文档指针。xmlParseFile函数以默认方式读入一个UTF-8格式的文档,并返回文档指针。xmlReadFile函数读入一个带有某种编码的xml文档,并返回文档指针;细节见libxml2参考手册。xmlFreeDoc释放文档指针。特别注意,当你调用xmlFreeDoc时,该文档所有包含的节点内存都被释放,所以一般来说不需要手动调用xmlFreeNode或者xmlFreeNodeList来释放动态分配的节点内存,除非你把该节点从文档中移除了。一般来说,一个文档中所有节点都应该动态分配,然后加入文档
37、,最后调用xmlFreeDoc一次释放所有节点申请的动态内存,这也是为什么我们很少看见xmlNodeFree的原因。xmlSaveFile将文档以默认方式存入一个文件。xmlSaveFormatFileEnc可将文档以某种编码/格式存入一个文件中。5)节点类型xmlNode、指针xmlNodePtr节点应该是xml中最重要的元素了,xmlNode代表了xml文档中的一个节点,实现为一个struct,内容很丰富:tree.htypedef struct _xmlNode xmlNode;typedef xmlNode *xmlNodePtr;struct _xmlNode void *_priv
38、ate;/* 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 _x
39、mlNode *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 */
40、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可以组织为树。同时还有以下重要元素:l节点中的文字内容:content;l节点所属文档:doc;
41、l节点名字:name;l节点的namespace:ns;l节点属性列表:properties;Xml文档的操作其根本原理就是在节点之间移动、查询节点的各项信息,并进行增加、删除、修改的操作。xmlDocSetRootElement函数可以将一个节点设置为某个文档的根节点,这是将文档与节点连接起来的重要手段,当有了根结点以后,所有子节点就可以依次连接上根节点,从而组织成为一个xml树。6)节点集合类型xmlNodeSet、指针xmlNodeSetPtr节点集合代表一个由节点组成的变量,节点集合只作为Xpath的查询结果而出现(XPATH的介绍见后面),因此被定义在xpath.h中,其定义如下:/
42、* A node-set (an unordered collection of nodes without duplicates).*/typedef struct _xmlNodeSet xmlNodeSet;typedef xmlNodeSet *xmlNodeSetPtr;struct _xmlNodeSet int nodeNr; /* number of nodes in the set */ int nodeMax; /* size of the array as allocated */ xmlNodePtr *nodeTab;/* array of nodes in no p
43、articular order */ /* with_ns to check wether namespace nodes should be looked at */;可以看出,节点集合有三个成员,分别是节点集合的节点数、最大可容纳的节点数,以及节点数组头指针。对节点集合中各个节点的访问方式很简单,如下:xmlNodeSetPtr nodeset = XPATH查询结果;for (int i = 0; i nodeNr; i+)nodeset-nodeTabi;注意,libxml2是一个c函数库,因此其函数和数据类型都使用c语言的方式来处理。如果是c+,我想我宁愿用STL中的vector来表
44、示一个节点集合更好,而且没有内存泄漏或者溢出的担忧。五、使用Libxml2项目中要实现一个管理XML文件的后台程序,需要对XML文件进行创建,解析,修改,查找等操作,下面介绍如何利用libxml2提供的库来实现上述功能。1、创建XML文档:我们使用xmlNewDoc()来创建XML文档,然后使用xmlNewNode(),xmlNewChild(),xmlNewProp(),xmlNewText()等函数向XML文件中添加节点及子节点,设置元素和属性,创建完毕后用xmlSaveFormatFileEnc()来保存XML文件到磁盘(该函数可以设置保存XML文件时的编码格式)。示例1: #inclu
45、de #include #include int main(int argc, char *argv) xmlDocPtr doc = NULL; /* document pointer */ xmlNodePtr root_node = NULL, node = NULL, node1 = NULL;/* node pointers */ / Creates a new document, a node and set it as a root node doc = xmlNewDoc(BAD_CAST 1.0); root_node = xmlNewNode(NULL, BAD_CAST root); xmlD