IBM Support

使用XML Toolkit for IBM i 解析XML文件

Technical Blog Post


Abstract

使用XML Toolkit for IBM i 解析XML文件

Body

XML Toolkit for IBM iIBM i上的License Program,用于提供在IBM i 上的XML解析及XSL转换的功能。最新版本5733XT2提供了支持C++XML解析器——XML4C,以及支持Procedural Language(如ILE C, RPG, COBOL)的XML解析器——XML4PR。本文将以RPG语言为例,简要介绍使用XML Toolkit for IBM iXML文件进行解析的方法。

 

(一)XML Toolkit for IBM i的各个组件

在安装完5733XT2产品的Option67之后,通过WRKLIB QXML563V6命令查看安装完成后的组件。

图像 

 
 
  图像
 
 
 
 
 
 
图像 
 
 
 
 
 
 
可以看到该目录下有5个组件。各个组件的含义如下: 

H——头文件目录

QCBLLESRC ——COBOL语言版本的范例代码目录

QCLSRC——编译范例代码的CL语言代码

QCSRC——C语言版本的范例代码目录   

QRPGLESRC——RPG语言版本的范例代码目录

另外在IFS路径/qibm/proddata/xmltoolkitv6/xml5_6_3/samples/之下,放置了所有C++语言的范例代码。路径/qibm/proddata/xmltoolkitv6/xml5_6_3/doc/之下,拥有详细的产品说明文档。

 

(二)编译、运行范例代码

RPG语言为例,使用如下命令将范例代码编译成可执行程序:

CRTCLPGM [CLLIB]/CRTXMLRPG QXML563V6/QCLSRC

CALL [CLLIB]/CRTXMLRPG [RPGLIB]

其中[CLLIB]需要替换成放置编译后的CL程序的目录, [RPGLIB]需要替换成保存这些编译完成后的RPG程序的目录名。

这里以新创建的XMLRPG为例,RPG目录设置为XMLPR563V6。依次输入

CRTLIB XMLRPG

CRTCLPGM XMLRPG/CRTXMLRPG QXML563V6/QCLSRC

CALL XMLRPG/CRTXMLRPG XMLPR563V6

三条命令。其中第三条命令需要执行较长时间,因为涉及到大量代码的编译。全部完成后,显示如下:

图像  

 

 
 
 
 
 
接下来我们尝试对IFS路径下的'/qibm/proddata/xmltoolkitv4/xml5_6_3/samples/data/personal.xml'文件进行解析。首先我们使用最基础的DOM解析器:

CALL XMLPR563V6/DOMCount ('/qibm/proddata/xmltoolkitv6/xml5_6_3/samples/data/personal.xml')

图像  

 

  

程序运行成功,解析完XML文件的结果显示该XML文件中包含有37个元素。 

图像  
 

 
 

同样我们可选用基于事件驱动SAX解析器来进行解析:

CALL XMLPR563V6/SAXCount ('/qibm/proddata/xmltoolkitv4/xml5_6_3/samples/data/personal.xml')

图像  
 
 
图像  
 
 
 
 

所有的范例程序包括CreateDocCreateXMLDOMPrintPParseSAXCountDOMCountMEMParseRedirectSAXPrintSAX2CountSAX2PrintSetRmvAttrXMLCalcXMLCalcMem。在'/qibm/proddata/xmltoolkitv4/xml5_6_3/doc/xml4pr/buildrpg.html'文件中有对各个范例程序的作用的介绍。

 

(三)使用RPG解析XML文件

对于使用DOM解析器解析XML文件的程序,至少应该包含下面几个基本组成部分。

(1)初始化环境

(2)创建解析器对象

(3)获取DOM对象

(4)操纵DOM树中的元素

(5)销毁DOM对象

(6)销毁解析器对象

(7)清理环境并退出

下面我们以一个简单的例子来说明基于DOM解析器的代码结构。代码中的XmlFilePath变量需要设置为待解析的XML文件的实际路径。

 /COPY QXML563V6/QRPGLESRC,QXML4PR563

 DEnvData@           S               *   INZ(%ADDR(Qxml_DomExcData))

 DPEnvData@         S               *   INZ(%ADDR(Qxml_SaxExcData))

 DDomParse@        S               *

 DDomDoc@          S               *

 *  Initialize XML environment

 C     CALLP     QxmlInit(EnvData@)

 C     EVAL       DomParse@ = QxmlXercesDOMParser_new(PEnvData@)

 C     CALLP     QxmlXercesDOMParser_parse_SystemId(

 C                DomParse@:

 C                XmlFilePath@:

 C                Qxml_CCSID37:

 C                0)

 C     EVAL       DomDoc@ = QxmlXercesDOMParser_getDocument(DomParse@)

 *  DOM elements manipulations...

 *  Cleanup any object allocations

 C     CALLP     QxmlDOMDocument_delete(DomDoc@)

 C     CALLP     QxmlXercesDOMParser_delete(DomParse@)

 *  Call XML termination

 C     CALLP     QxmlTerm

这段代码首先是初始化XML解析器的环境,使用的是QxmlInit函数。然后使用了QxmlXercesDOMParser_new函数创建一个解析器对象DomParse。并将需要处理的XML文件名设置好。此后可以为这个解析器设置各类属性,例如validationnamespace,schema选项等等。

DOMCOUNT这个程序中,需要根据解析后的XML文件内容在内存中创建一个DOM树。这里就用到了QxmlXercesDOMParser_getDocument函数来创建DOM树。得到DOM树后便可以对树中的元素进行各类操作了。

在操作完毕后,需要按照与创建过程相反的顺序依次销毁创建的对象。首先销毁内存中创建的DOM树,然后是解析器,最后通过QxmlTerm函数终结程序。

对于SAX解析器,其程序结构大体上与DOM解析器类似。同样是由QxmlInit函数初始化环境,然后创建解析器进行解析,解析完毕后清理资源,最后使用QxmlTerm结束。但是因为SAX解析器是基于事件驱动的模型,因此不存在DOM树的内存结构。相对应的,SAX解析器依赖于不同事件的各个回调函数工作,因此SAX程序的功能主体往往是由大量的回调函数组成。一般而言这些回调函数的注册是在创建解析器后进行的。

 *  Initialize XML environment

C     CALLP     QxmlInit(ENVDATA@)                    

 *  Create a SAX Parser object, set various input options           

C     EVAL       SAXParse@ = QxmlSAXPARSER_new         

 *  Create a document and error handler and register with parser 

C     EVAL       DOCHNDLR@ = QxmlDocumentHandler_new

C     EVAL       ERRHNDLR@ = QxmlErrorHandler_new   

C     CALLP     QxmlSAXParser_setDocumentHandler(SAXParse@:DOCHNDLR@)                 

C     CALLP     QxmlSAXParser_setErrorHandler(SAXParse@:ERRHNDLR@)             

 *  Register the callback routines based on specific SAX Document    

 *  and Error handler events (such as STARTDOUCMENT, CHARACTERS, etc)

C     CALLP     QxmlDocumentHandler_setCallback()

……                         

 *  Call parser providing XML file name                            

C     CALLP     QxmlSAXParser_parse_systemid(SAXParse@:XmlFile@:Qxml_CCSID37:0)       

 *  Cleanup any object allocations                      

C     CALLP     QxmlDocumentHandler_delete(DOCHNDLR@)

C     CALLP     QxmlErrorHandler_delete(ERRHNDLR@)   

C     CALLP     QxmlSAXPARSER_delete(SAXParse@)      

C     CALLP     QxmlTerm   

 *  Many Call back functions

…… 

通过以上两个程序片段,我们可以看到使用RPG语言解析XML文件的通用代码结构。在解析器的选择上,如果解析的XML文件体积较小,并且需要随机访问某个不特定元素的属性,那么DOM解析器是一个较好的选择。而如果解析的XML文件过大,那么基于事件驱动的SAX解析器将会更具优势。

*除了上面两个简单的程序之外,我们还可以通过STRPDM命令查看附带的大量示例程序的源代码。

图像  
 
 
 

 
 
 
 
打开QXML563V6下面的QRPGLESRC文件。 
图像  
 
 
 

 
 
 
 
 
使用选项5来查看感兴趣的范例程序源代码。
图像  
 
 
 
 
 
 
 
 
 
 
 
作者:Xu Meng
 

[{"Business Unit":{"code":"BU058","label":"IBM Infrastructure w\/TPS"},"Product":{"code":"SWG60","label":"IBM i"},"Component":"","Platform":[{"code":"PF025","label":"Platform Independent"}],"Version":"","Edition":"","Line of Business":{"code":"LOB57","label":"Power"}}]

UID

ibm11145260