PLSQL解析XML.docx
《PLSQL解析XML.docx》由会员分享,可在线阅读,更多相关《PLSQL解析XML.docx(11页珍藏版)》请在冰豆网上搜索。
PLSQL解析XML
使用PL/SQL程序如何解析XML
(原创)
学习篇--XML文件解析
文档作者:
Siman.He<贺斌>
MSN:
*********************
创建日期:
2009-5-22
更新日期:
2009-5-22
文档编号:
当前版本:
Draft1.0
Note:
Title,Subject,LastUpdatedDate,ReferenceNumber,andVersionaremarkedbyaWordBookmarksothattheycanbeeasilyreproducedintheheaderandfooterofdocuments.Whenyouchangeanyofthesevalues,becarefulnottoaccidentallydeletethebookmark.YoucanmakebookmarksvisiblebyselectingTools->Options…ViewandcheckingtheBookmarksoptionintheShowregion.
文档控制
变更记录
日期
作者
版本
变更说明
07/04/08
IBM
1.0
初版
审阅
姓名
职位
分发
拷贝编号
姓名
位置/岗位
1
资料室主管
项目资料室
2
项目组成员
3
4
Note:
ThecopynumbersreferencedaboveshouldbewrittenintotheCopyNumberspaceonthecoverofeachdistributedcopy.Ifthedocumentisnotcontrolled,youcandeletethistable,theNoteToHolders,andtheCopyNumberlabelfromthecoverpage.
Note:
Toupdatethetableofcontents,putthecursoranywhereinthetableandpress[F9].Tochangethenumberoflevelsdisplayed,selectthemenuoptionInsert>IndexandTables,makesuretheTableofContentstabisactive,andchangetheNumberofLevelstoanewvalue.
概述
使用XML文件传输数据,现在已经被越来越多的项目所采纳。
其做法通常是用额外开发的java程序来解析XML数据。
其实Oracle已经为XML配备了一套功能健全的工具集,该工具集允许PL/SQL和Java开发人员在Oracle数据库内部进行工作。
本文简要地概述了XML特性和适用于Oracle数据库的实用程序,描述如何设置并使用面向XML的OraclePL/SQL分析程序,然后介绍了一个实例程序,该程序分析PL/SQL内的XML信息。
XML组建
在PL/SQL中利用XML,Oracle提供了几个组件,让开发人员能轻松地利用XML技术。
这些组件包括:
1.XML分析程序。
即用来分析、构造和验证XML文档。
.
2.XPath引擎。
它是使用Xpath(XML标准的另一个元素)说明语法在内存中搜索XML文档的实用程序。
SLT处理器。
它在Oracle数据库中支持XSLT,允许您把XML文档转换成其他格式。
3.XMLSQL实用程序。
可以使用SQL产生XML文档,使您可以在Oracle数据库表格中轻松地插入基于XML的数据。
XSQL页。
一项可以汇集声明性XML数据然后通过XSLT公布这些数据的技术。
对于PL/SQL开发人员而言,XML分析程序是最重要的组件。
通过它,您可以在Oracle数据库中分析、操纵和转换XML文档。
ML分析程序由一套APIs(应用程序编程接口)构成。
XML结构图
XML常用的分析函数
XMLParser
包括分析XML文档所需的数据类型和程序。
XMLParsingProcess
想知道Oracle的parser是如何调用Java来做解析的,请查看Oracle®XMLDeveloper'sKitProgrammer'sGuide
10gRelease2(10.2)
PartNumberB14252-01
网址:
程序中常用的方法:
Nodelist:
=dbms_xslprocessor.selectnodes(rootnode,xpath)
dbms_xslprocessor.valueof(节点,节点下的元素,值)
具体的实例,会在下面讲解。
XMLDOM
包括管理和建立XML文档对象模型(DOM)元素所需的数据类型和程序
ComparingDOM(Tree-Based)andSAX(Event-Based)APIs
XMLDOM这个程序包,其实是通过封装Java程序来解析XML的一个PL/SQL的包。
具体的作用还是要参考Oracle®DatabasePL/SQLPackagesandTypesReference
10gRelease2(10.2)
PartNumberB14258-02
网址:
XML解析实例
案列:
XML文件:
simanhe_test.xml
xmlversion="1.0"encoding="UTF-8"?
>
200
1
测试1
滘滘生僻字
测试2
看一看
测试3
瞅一瞅
测试4
试一试
测试5
爽一爽
文件的结构
解析方案
在XMLDOM的解析过程中,如果想找某个节点(Fitem)的属性(RecErrCode),而该节点又不是根节点时,需要从最小的节点往上找父节点,一直到节点Fitem,然后在得到其属性。
如果节点是根节点,则可以直接得到根节点的元素和属性的值。
根据上图所示,我们要找根节点Dfile的元素和属性的值,直接调用。
XML解析脚本
Oracle通过调用APIxmldom和dbms_xmlparser来做XML文件的解析。
1. 建立一个Directory,假如在EBS上实现则需要在EBSDB的服务器上建立路径 如:
CreateOrReplaceDirectoryFTP_XXXAs'/var/tmp/ftp'直接在APPS下就可以新建
要查找当前建立的Directory可以使用Select*Fromall_directories查找当前系统中的所有的Directory.
2.代码如下
DECLARE
p_max_sizeNUMBER:
=dbms_lob.lobmaxsize;
src_offsetNUMBER:
=1;
dst_offsetNUMBER:
=1;
lang_ctxNUMBER:
=nls_charset_id('UTF8');
default_csidCONSTANTINTEGER:
=nls_charset_id('ZHS16GBK');
warningNUMBER;
l_file_numberPLS_INTEGER:
=0;
l_countNUMBER;
l_bfileBFILE;
l_clobCLOB;
l_commitelementxmldom.domelement;
l_parserdbms_xmlparser.parser;
l_docdbms_xmldom.domdocument;
l_nldbms_xmldom.domnodelist;
l_ndbms_xmldom.domnode;
rootnodedbms_xmldom.domnode;
parent_rootnodedbms_xmldom.domnode;
file_lengthNUMBER;
block_sizeBINARY_INTEGER;
l_rootnode_nameVARCHAR2(200);
l_statusVARCHAR2(1000);
l_recerrcodeVARCHAR2(1000);
l_FailCountVARCHAR2(200);
l_RecCountVARCHAR2(200);
l_nameVARCHAR2(1000);
l_commentsVARCHAR2(2000);
l_existsBOOLEAN;
FUNCTIONconvertclobtoxmlelement(p_documentINCLOB)
RETURNxmldom.domelementIS
x_commitelementxmldom.domelement;
l_parserxmlparser.parser;
BEGIN
l_parser:
=xmlparser.newparser;
xmlparser.parseclob(l_parser,p_document);
x_commitelement:
=xmldom.getdocumentelement(xmlparser.getdocument(l_parser));
RETURNx_commitelement;
ENDconvertclobtoxmlelement;
BEGIN
--检查XML是否在路径FTP_XXX下是否存在
utl_file.fgetattr('FTP_XXX',
'simanhe_test.xml',
l_exists,
file_length,
block_size);
IFNOTl_existsTHEN
dbms_output.put_line('XML文件不存在');
RETURN;
ENDIF;
l_bfile:
=bfilename('FTP_XXX','simanhe_test.xml');
--创建一个Clob
dbms_lob.createtemporary(l_clob,TRUE);
dbms_lob.OPEN(l_bfile,dbms_lob.lob_readonly);
--将XML文件上载并转换为Clob类型
dbms_lob.loadclobfromfile(l_clob,
l_bfile,
p_max_size,
dst_offset,
src_offset,
default_csid,--UTF8
lang_ctx,--GBK
warning);
l_file_number:
=dbms_lob.fileexists(l_bfile);
IFl_file_number=0THEN
dbms_output.put_line('XML文件未被转换成功');
RETURN;
ENDIF;
dbms_lob.CLOSE(l_bfile);
--Createaparser.
l_parser:
=dbms_xmlparser.newparser;
BEGIN
--ParsethedocumentandcreateanewDOMdocument.
dbms_xmlparser.parseclob(l_parser,l_clob);
EXCEPTION
WHENOTHERSTHEN
dbms_output.put_line('XML文件不完整');
RETURN;
END;
l_doc:
=dbms_xmlparser.getdocument(l_parser);
--FreeresourcesassociatedwiththeCLOBandParsernowtheyarenolongerneeded.
dbms_lob.freetemporary(l_clob);
--得到根节点
rootnode:
=xmldom.makenode(xmldom.getdocumentelement(xmlparser.getdocument(l_parser)));
l_rootnode_name:
=xmldom.getnodename(rootnode);
dbms_output.put_line('XML文件当前的节点名称为'||l_rootnode_name);
--得到根节点元素的值
dbms_xslprocessor.valueof(rootnode,'RecCount/text()',l_RecCount);
dbms_xslprocessor.valueof(rootnode,'FailCount/text()',l_FailCount);
dbms_output.put_line('XML文件当前的节点名称为'||l_rootnode_name||
'的要素RecCount,FailCount值为'||l_RecCount||','||l_FailCount);
--得到根节点Dfile的属性Status的值
l_status:
=xmldom.getattribute(xmldom.makeelement(rootnode),'Status');
dbms_output.put_line('XML文件当前的节点名称为'||l_rootnode_name||
'的属性Status的值为'||l_status);
/*取节点Item下各元素的值,先将Items节点全部存放在l_nl中*/
l_nl:
=dbms_xmldom.getelementsbytagname(l_doc,'Item');
l_count:
=dbms_xmldom.getlength(l_nl);
FORcur_empIN0..dbms_xmldom.getlength(l_nl)-1LOOP
l_n:
=dbms_xmldom.item(l_nl,cur_emp);
--得到节点Item下元素的值
dbms_xslprocessor.valueof(l_n,'Name/text()',l_name);
dbms_xslprocessor.valueof(l_n,'Comment/text()',l_comments);
--得到节点Item的父节点FItem
parent_rootnode:
=dbms_xmldom.getparentnode(l_n);
l_rootnode_name:
=xmldom.getnodename(parent_rootnode);
--得到节点FItem的属性RecErrCode的值
l_recerrcode:
=xmldom.getattribute(xmldom.makeelement(parent_rootnode),
'RecErrCode');
dbms_output.put_line('Name:
'||l_name||',Comment='||
l_comments||',RecErrCode='||l_recerrcode);
ENDLOOP;
--释放分析函数的资源
dbms_xmlparser.freeparser(l_parser);
--将DOC清空,释放资源
dbms_xmldom.freedocument(l_doc);
/*utl_file.frename('FTP_XXX',
'simanhe_test.xml',
'FTP_XXX',
'D_simanhe_test.xml',
FALSE);*/--XML文件解析完成后重命名
/*utl_file.fremove('FTP_XXX','simanhe_test.xml');*/----XML文件解析完成后删除文件
EXCEPTION
WHENOTHERSTHEN
dbms_lob.freetemporary(l_clob);
dbms_xmlparser.freeparser(l_parser);
dbms_xmldom.freedocument(l_doc);
END;
以上程序经测试是可以正常运行的。
但是对XML文件的大小有要求,最好不要超过10M。
文件的个头越大解析的效率会越差。
我一般建议XML文件大小为2M左右,另外对一些生僻字我在上载XML文件的时候就已经将其转化为ZHS16GBK了,所以不存在乱码的问题。
以上的脚本可以给大家提供一个参考,希望能对大伙有所帮助。
更改历史